diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/AppFeature.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/AppFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..f456abbc6723aaeea5b0855be66dfd2b2bcc16b8
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/AppFeature.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AppFeature"
+               BuildableName = "AppFeature"
+               BlueprintName = "AppFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AppFeature"
+            BuildableName = "AppFeature"
+            BlueprintName = "AppFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/AppNavigation.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/AppNavigation.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..15cbf312c024090afcf8a19dc2a95dc46942b6ae
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/AppNavigation.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AppNavigation"
+               BuildableName = "AppNavigation"
+               BlueprintName = "AppNavigation"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AppNavigation"
+            BuildableName = "AppNavigation"
+            BlueprintName = "AppNavigation"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Defaults.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Defaults.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..8d32953525d76ceaaeafe999fcdec2c2b6a64c44
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/Defaults.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "Defaults"
+               BuildableName = "Defaults"
+               BlueprintName = "Defaults"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "Defaults"
+            BuildableName = "Defaults"
+            BlueprintName = "Defaults"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Keychain.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Keychain.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..e1efe3f4ab10b6ff34298955c87ae081d23eafea
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/Keychain.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "Keychain"
+               BuildableName = "Keychain"
+               BlueprintName = "Keychain"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "Keychain"
+            BuildableName = "Keychain"
+            BlueprintName = "Keychain"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/SettingsFeature.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SettingsFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..244b1a0ce2d97ea860b30062ec59ec322e831e1a
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/SettingsFeature.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "SettingsFeature"
+               BuildableName = "SettingsFeature"
+               BlueprintName = "SettingsFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "SettingsFeature"
+            BuildableName = "SettingsFeature"
+            BlueprintName = "SettingsFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/UpdateErrors.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/UpdateErrors.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..1998517fa48f8d42029ba164bc4429012ad24652
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/UpdateErrors.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "UpdateErrors"
+               BuildableName = "UpdateErrors"
+               BlueprintName = "UpdateErrors"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "UpdateErrors"
+            BuildableName = "UpdateErrors"
+            BlueprintName = "UpdateErrors"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/Package.swift b/Package.swift
index 79eb6ae391a45399efb0dce157a0239cdfa40c29..b1ec908e6564028f197b352659674d5c971a15ad 100644
--- a/Package.swift
+++ b/Package.swift
@@ -12,30 +12,37 @@ let package = Package(
     .library(name: "AppCore", targets: ["AppCore"]),
     .library(name: "Defaults", targets: ["Defaults"]),
     .library(name: "Keychain", targets: ["Keychain"]),
+    .library(name: "Voxophone", targets: ["Voxophone"]),
     .library(name: "AppFeature", targets: ["AppFeature"]),
     .library(name: "InputField", targets: ["InputField"]),
     .library(name: "ScanFeature", targets: ["ScanFeature"]),
     .library(name: "MenuFeature", targets: ["MenuFeature"]),
     .library(name: "ChatFeature", targets: ["ChatFeature"]),
     .library(name: "PushFeature", targets: ["PushFeature"]),
+    .library(name: "CrashReport", targets: ["CrashReport"]),
+    .library(name: "UpdateErrors", targets: ["UpdateErrors"]),
+    .library(name: "CheckVersion", targets: ["CheckVersion"]),
     .library(name: "AppResources", targets: ["AppResources"]),
-    .library(name: "CrashService", targets: ["CrashService"]),
     .library(name: "TermsFeature", targets: ["TermsFeature"]),
+    .library(name: "AppNavigation", targets: ["AppNavigation"]),
     .library(name: "BackupFeature", targets: ["BackupFeature"]),
     .library(name: "LaunchFeature", targets: ["LaunchFeature"]),
     .library(name: "SearchFeature", targets: ["SearchFeature"]),
     .library(name: "DrawerFeature", targets: ["DrawerFeature"]),
+    .library(name: "WebsiteFeature", targets: ["WebsiteFeature"]),
     .library(name: "RestoreFeature", targets: ["RestoreFeature"]),
-    .library(name: "CrashReporting", targets: ["CrashReporting"]),
     .library(name: "ProfileFeature", targets: ["ProfileFeature"]),
     .library(name: "ContactFeature", targets: ["ContactFeature"]),
+    .library(name: "FetchBannedList", targets: ["FetchBannedList"]),
     .library(name: "SettingsFeature", targets: ["SettingsFeature"]),
     .library(name: "ChatListFeature", targets: ["ChatListFeature"]),
     .library(name: "RequestsFeature", targets: ["RequestsFeature"]),
     .library(name: "ReportingFeature", targets: ["ReportingFeature"]),
-    .library(name: "StatusBarFeature", targets: ["StatusBarFeature"]),
     .library(name: "ChatInputFeature", targets: ["ChatInputFeature"]),
+    .library(name: "GroupDraftFeature", targets: ["GroupDraftFeature"]),
+    .library(name: "ProcessBannedList", targets: ["ProcessBannedList"]),
     .library(name: "OnboardingFeature", targets: ["OnboardingFeature"]),
+    .library(name: "CreateGroupFeature", targets: ["CreateGroupFeature"]),
     .library(name: "CountryListFeature", targets: ["CountryListFeature"]),
     .library(name: "PermissionsFeature", targets: ["PermissionsFeature"]),
     .library(name: "ContactListFeature", targets: ["ContactListFeature"]),
@@ -118,13 +125,6 @@ let package = Package(
       url: "https://github.com/pointfreeco/xctest-dynamic-overlay.git",
       .upToNextMajor(from: "0.3.3")
     ),
-    .package(
-      path: "../xxm-navigation"
-    ),
-    .package(
-      url: "https://git.xx.network/elixxir/xxm-di",
-      .upToNextMajor(from: "1.0.0")
-    )
   ],
   targets: [
     .target(
@@ -135,24 +135,25 @@ let package = Package(
         .target(name: "ScanFeature"),
         .target(name: "ChatFeature"),
         .target(name: "MenuFeature"),
+        .target(name: "CrashReport"),
         .target(name: "PushFeature"),
         .target(name: "TermsFeature"),
-        .target(name: "CrashService"),
         .target(name: "BackupFeature"),
         .target(name: "SearchFeature"),
         .target(name: "LaunchFeature"),
         .target(name: "ContactFeature"),
+        .target(name: "WebsiteFeature"),
         .target(name: "RestoreFeature"),
         .target(name: "ProfileFeature"),
-        .target(name: "CrashReporting"),
         .target(name: "ChatListFeature"),
         .target(name: "SettingsFeature"),
         .target(name: "RequestsFeature"),
         .target(name: "ReportingFeature"),
+        .target(name: "GroupDraftFeature"),
         .target(name: "OnboardingFeature"),
+        .target(name: "CreateGroupFeature"),
         .target(name: "ContactListFeature"),
         .target(name: "RequestPermissionFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
       ]
     ),
     .testTarget(
@@ -166,7 +167,6 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "AppResources"),
-        .target(name: "StatusBarFeature"),
         .product(name: "SnapKit", package: "SnapKit"),
         .product(name: "Logging", package: "swift-log"),
         .product(name: "XXModels", package: "client-ios-db"),
@@ -177,31 +177,56 @@ let package = Package(
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
       ]
     ),
+    .target(name: "CheckVersion"),
+    .target(name: "Voxophone"),
+    .target(name: "WebsiteFeature"),
     .target(
-      name: "CrashReporting"
+      name: "CrashReport",
+      dependencies: [
+        .product(
+          name: "FirebaseCrashlytics",
+          package: "firebase-ios-sdk"
+        ),
+        .product(
+          name: "Dependencies",
+          package: "swift-composable-architecture"
+        ),
+      ]
     ),
     .target(
-      name: "PermissionsFeature",
+      name: "AppNavigation",
       dependencies: [
         .product(
-          name: "XCTestDynamicOverlay",
-          package: "xctest-dynamic-overlay"
+          name: "XXModels",
+          package: "client-ios-db"
         ),
         .product(
-          name: "ComposableArchitecture",
+          name: "Dependencies",
           package: "swift-composable-architecture"
         ),
       ]
     ),
     .target(
-      name: "StatusBarFeature",
+      name: "CreateGroupFeature",
+      dependencies: [
+        .target(name: "AppCore")
+      ]
+    ),
+    .target(
+      name: "GroupDraftFeature",
+      dependencies: [
+        .target(name: "AppCore")
+      ]
+    ),
+    .target(
+      name: "PermissionsFeature",
       dependencies: [
         .product(
           name: "XCTestDynamicOverlay",
           package: "xctest-dynamic-overlay"
         ),
         .product(
-          name: "ComposableArchitecture",
+          name: "Dependencies",
           package: "swift-composable-architecture"
         ),
       ]
@@ -222,10 +247,12 @@ let package = Package(
       name: "RequestPermissionFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .target(name: "AppResources"),
+        .target(name: "AppNavigation"),
         .target(name: "PermissionsFeature"),
         .product(
-          name: "ComposableArchitecture",
+          name: "Dependencies",
           package: "swift-composable-architecture"
         ),
       ]
@@ -233,9 +260,9 @@ let package = Package(
     .target(
       name: "PushFeature",
       dependencies: [
+        .target(name: "AppCore"),
         .target(name: "Defaults"),
         .target(name: "ReportingFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "XXDatabase", package: "client-ios-db"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
@@ -249,22 +276,13 @@ let package = Package(
     ),
     .target(
       name: "Defaults",
-      dependencies: [
-        .product(name: "DependencyInjection", package: "xxm-di"),
-      ]
-    ),
-    .target(
-      name: "CrashService",
-      dependencies: [
-        .target(name: "CrashReporting"),
-        .product(name: "FirebaseCrashlytics", package: "firebase-ios-sdk"),
-      ]
+      dependencies: []
     ),
     .target(
       name: "CountryListFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "StatusBarFeature")
+        .target(name: "AppCore")
       ]
     ),
     .target(
@@ -293,6 +311,9 @@ let package = Package(
     .target(
       name: "ChatInputFeature",
       dependencies: [
+        .target(
+          name: "Voxophone"
+        ),
         .product(
           name: "ComposableArchitecture",
           package: "swift-composable-architecture"
@@ -303,9 +324,8 @@ let package = Package(
       name: "RestoreFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .product(name: "XXDatabase", package: "client-ios-db"),
-        .product(name: "Navigation", package: "xxm-navigation"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "CloudFilesDrive", package: "xxm-cloud-providers"),
         .product(name: "CloudFilesDropbox", package: "xxm-cloud-providers"),
@@ -327,13 +347,14 @@ let package = Package(
       name: "ChatFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
+        .target(name: "Voxophone"),
         .target(name: "DrawerFeature"),
         .target(name: "ChatInputFeature"),
         .target(name: "ReportingFeature"),
         .target(name: "RequestPermissionFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "ChatLayout", package: "ChatLayout"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
@@ -351,7 +372,6 @@ let package = Package(
         .target(name: "CountryListFeature"),
         .product(name: "Retry", package: "Retry"),
         .product(name: "XXDatabase", package: "client-ios-db"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
       ]
     ),
     .target(
@@ -360,8 +380,12 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "PushFeature"),
+        .target(name: "UpdateErrors"),
+        .target(name: "CheckVersion"),
         .target(name: "BackupFeature"),
+        .target(name: "FetchBannedList"),
         .target(name: "ReportingFeature"),
+        .target(name: "ProcessBannedList"),
         .target(name: "RequestPermissionFeature"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "CloudFilesSFTP", package: "xxm-cloud-providers"),
@@ -376,7 +400,54 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "Defaults"),
-        .product(name: "Navigation", package: "xxm-navigation"),
+        .target(name: "AppNavigation"),
+      ]
+    ),
+    .target(
+      name: "UpdateErrors",
+      dependencies: [
+        .product(
+          name: "XXClient",
+          package: "elixxir-dapps-sdk-swift"
+        ),
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
+        .product(
+          name: "Dependencies",
+          package: "swift-composable-architecture"
+        ),
+      ]
+    ),
+    .target(
+      name: "ProcessBannedList",
+      dependencies: [
+        .product(
+          name: "SwiftCSV",
+          package: "SwiftCSV"
+        ),
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
+        .product(
+          name: "Dependencies",
+          package: "swift-composable-architecture"
+        ),
+      ]
+    ),
+    .target(
+      name: "FetchBannedList",
+      dependencies: [
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
+        .product(
+          name: "Dependencies",
+          package: "swift-composable-architecture"
+        ),
       ]
     ),
     .target(
@@ -384,8 +455,10 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "ContactFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
-        .product(name: "DifferenceKit", package: "DifferenceKit"),
+        .product(
+          name: "DifferenceKit",
+          package: "DifferenceKit"
+        ),
       ]
     ),
     .target(
@@ -400,8 +473,6 @@ let package = Package(
         .target(name: "BackupFeature"),
         .target(name: "CountryListFeature"),
         .target(name: "RequestPermissionFeature"),
-        .product(name: "Navigation", package: "xxm-navigation"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
@@ -418,7 +489,6 @@ let package = Package(
         .target(name: "ProfileFeature"),
         .target(name: "SettingsFeature"),
         .target(name: "ContactListFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
       ]
     ),
@@ -432,6 +502,7 @@ let package = Package(
         .target(name: "InputField"),
         .target(name: "PushFeature"),
         .target(name: "DrawerFeature"),
+        .target(name: "AppNavigation"),
         .target(name: "CountryListFeature"),
         .target(name: "RequestPermissionFeature"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
@@ -443,12 +514,14 @@ let package = Package(
       name: "MenuFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .target(name: "Defaults"),
         .target(name: "DrawerFeature"),
         .target(name: "ReportingFeature"),
-        .product(name: "Navigation", package: "xxm-navigation"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
-        .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
+        .product(
+          name: "XXClient",
+          package: "elixxir-dapps-sdk-swift"
+        ),
       ]
     ),
     .target(
@@ -458,10 +531,6 @@ let package = Package(
         .target(name: "AppCore"),
         .target(name: "InputField"),
         .target(name: "DrawerFeature"),
-        .product(
-          name: "Navigation",
-          package: "xxm-navigation"
-        ),
         .product(
           name: "XXClient",
           package: "elixxir-dapps-sdk-swift"
@@ -499,7 +568,6 @@ let package = Package(
         .target(name: "ContactFeature"),
         .target(name: "CountryListFeature"),
         .target(name: "RequestPermissionFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "SnapKit", package: "SnapKit"),
       ]
     ),
@@ -508,7 +576,6 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "ContactFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
       ]
     ),
@@ -521,9 +588,9 @@ let package = Package(
         .target(name: "InputField"),
         .target(name: "PushFeature"),
         .target(name: "MenuFeature"),
+        .target(name: "CrashReport"),
         .target(name: "DrawerFeature"),
         .target(name: "RequestPermissionFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
@@ -533,7 +600,6 @@ let package = Package(
       dependencies: [
         .target(name: "DrawerFeature"),
         .target(name: "Shared"),
-        .product(name: "SwiftCSV", package: "SwiftCSV"),
         .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
       ],
       resources: [
diff --git a/Sources/AppCore/AppDependencies.swift b/Sources/AppCore/AppDependencies.swift
index 1f3ec64e5898e606f93ed1e8957a6f7a2279d3ba..f974596a680bfe8b671315094fc07287bb661787 100644
--- a/Sources/AppCore/AppDependencies.swift
+++ b/Sources/AppCore/AppDependencies.swift
@@ -1,13 +1,16 @@
+import XXClient
 import Foundation
 import XXMessengerClient
 import XCTestDynamicOverlay
 import ComposableArchitecture
 
 public struct AppDependencies {
-  public var networkMonitor: NetworkMonitorManager
+  public var networkMonitor: NetworkMonitor
   public var toastManager: ToastManager
+  public var backupHandler: BackupCallbackHandler
   public var hudManager: HUDManager
   public var dbManager: DBManager
+  public var statusBar: StatusBarStylist
   public var messenger: Messenger
   public var authHandler: AuthCallbackHandler
   public var backupStorage: BackupStorage
@@ -24,7 +27,11 @@ public struct AppDependencies {
 
 extension AppDependencies {
   public static func live() -> AppDependencies {
-    let dbManager = DBManager.live()
+    let dbManager = DBManager.live(
+      url: FileManager.default.containerURL(
+        forSecurityApplicationGroupIdentifier: "group.elixxir.messenger"
+      )!
+    )
     var messengerEnv = MessengerEnvironment.live()
     messengerEnv.udEnvironment = .init(
       address: Constants.address,
@@ -41,12 +48,20 @@ extension AppDependencies {
     return AppDependencies(
       networkMonitor: .live(),
       toastManager: .live(),
+      backupHandler: .live(
+        messenger: messenger
+      ),
       hudManager: .live(),
       dbManager: dbManager,
+      statusBar: .live(),
       messenger: messenger,
       authHandler: .live(
         messenger: messenger,
-        handleRequest: .live(db: dbManager.getDB, now: now),
+        handleRequest: .live(
+          db: dbManager.getDB,
+          messenger: messenger,
+          now: now
+        ),
         handleConfirm: .live(db: dbManager.getDB),
         handleReset: .live(db: dbManager.getDB)
       ),
@@ -81,8 +96,10 @@ extension AppDependencies {
   public static let unimplemented = AppDependencies(
     networkMonitor: .unimplemented,
     toastManager: .unimplemented,
+    backupHandler: .unimplemented,
     hudManager: .unimplemented,
     dbManager: .unimplemented,
+    statusBar: .unimplemented,
     messenger: .unimplemented,
     authHandler: .unimplemented,
     backupStorage: .unimplemented,
@@ -142,3 +159,27 @@ tgH4rdEXuVe9+31oJhmXOE9ux2jCop9tEJMgWg7HStrJ5plPbb+HmjoX3nBO04E5
 <xxc(2)7mbKFLE201WzH4SGxAOpHjjehwztIV+KGifi5L/PYPcDkAZiB9kZo+Dl3Vc7dD2SdZCFMOJVgwqGzfYRDkjc8RGEllBqNxq2sRRX09iQVef0kJQUgJCHNCOcvm6Ki0JJwvjLceyFh36iwK8oLbhLgqEZY86UScdACTyBCzBIab3ob5mBthYc3mheV88yq5PGF2DQ+dEvueUm+QhOSfwzppAJA/rpW9Wq9xzYcQzaqc3ztAGYfm2BBAHS7HVmkCbvZ/K07Xrl4EBPGHJYq12tWAN/C3mcbbBYUOQXyEzbSl/mO7sL3ORr0B4FMuqCi8EdlD6RO52pVhY+Cg6roRH1t5Ng1JxPt8Mv1yyjbifPhZ5fLKwxBz8UiFORfk0/jnhwgm25LRHqtNRRUlYXLvhv0HhqyYTUt17WNtCLATSVbqLrFGdy2EGadn8mP+kQNHp93f27d/uHgBNNe7LpuYCJMdWpoG6bOqmHEftxt0/MIQA8fTtTm3jJzv+7/QjZJDvQIv0SNdp8HFogpuwde+GuS4BcY7v5xz+ArGWcRR63ct2z83MqQEn9ODr1/gAAAgA7szRpDDQIdFUQo9mkWg8xBA==xxc>
 """
 }
+
+private enum StoredDummyTrafficKey: DependencyKey {
+  static var liveValue = Stored<DummyTraffic?>.inMemory()
+  static var testValue = Stored<DummyTraffic?>.unimplemented()
+}
+
+extension DependencyValues {
+  public var dummyTraffic: Stored<DummyTraffic?> {
+    get { self[StoredDummyTrafficKey.self] }
+    set { self[StoredDummyTrafficKey.self] = newValue }
+  }
+}
+
+private enum StoredNewGroupChatKey: DependencyKey {
+  static var liveValue = Stored<GroupChat?>.inMemory()
+  static var testValue = Stored<GroupChat?>.unimplemented()
+}
+
+extension DependencyValues {
+  public var groupManager: Stored<GroupChat?> {
+    get { self[StoredNewGroupChatKey.self] }
+    set { self[StoredNewGroupChatKey.self] = newValue }
+  }
+}
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift
index c6e03cbedb7f1d0020d11a94c6fc0172a5fc5247..be0ca1047096e8390ce9b98b03a16b8906b878f2 100644
--- a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift
@@ -1,8 +1,8 @@
-import Foundation
-import XCTestDynamicOverlay
+import XXModels
 import XXClient
+import Foundation
 import XXMessengerClient
-import XXModels
+import XCTestDynamicOverlay
 
 public struct AuthCallbackHandler {
   public typealias OnError = (Error) -> Void
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift
index 2aa6787fff741651d649fb8f88397669b448d92f..60d86e9a66eb83a792aaa7d01b664fd62aaa47da 100644
--- a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift
@@ -18,6 +18,7 @@ extension AuthCallbackHandlerConfirm {
       guard var dbContact = try db().fetchContacts(.init(id: [id])).first else {
         return
       }
+      dbContact.isRecent = true
       dbContact.authStatus = .friend
       dbContact = try db().saveContact(dbContact)
     }
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift
index 6d1943e923732bc6dbdafe053deeb962191b7d13..4ea820682a7c8c5f772e77fba26b05f3aba94496 100644
--- a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift
@@ -1,8 +1,8 @@
-import Foundation
-import XCTestDynamicOverlay
+import XXModels
 import XXClient
+import Foundation
 import XXMessengerClient
-import XXModels
+import XCTestDynamicOverlay
 
 public struct AuthCallbackHandlerRequest {
   public var run: (XXClient.Contact) throws -> Void
@@ -15,6 +15,7 @@ public struct AuthCallbackHandlerRequest {
 extension AuthCallbackHandlerRequest {
   public static func live(
     db: DBManagerGetDB,
+    messenger: Messenger,
     now: @escaping () -> Date
   ) -> AuthCallbackHandlerRequest {
     AuthCallbackHandlerRequest { xxContact in
@@ -27,9 +28,21 @@ extension AuthCallbackHandlerRequest {
       dbContact.username = try xxContact.getFact(.username)?.value
       dbContact.email = try xxContact.getFact(.email)?.value
       dbContact.phone = try xxContact.getFact(.phone)?.value
-      dbContact.authStatus = .stranger
+      dbContact.authStatus = .verificationInProgress
       dbContact.createdAt = now()
       dbContact = try db().saveContact(dbContact)
+      do {
+        try messenger.waitForNetwork()
+        if try messenger.verifyContact(xxContact) {
+          dbContact.authStatus = .verified
+          dbContact = try db().saveContact(dbContact)
+        } else {
+          try db().deleteContact(dbContact)
+        }
+      } catch {
+        dbContact.authStatus = .verificationFailed
+        dbContact = try db().saveContact(dbContact)
+      }
     }
   }
 }
diff --git a/Sources/AppCore/BackupCallbackHandler/BackupCallbackHandler.swift b/Sources/AppCore/BackupCallbackHandler/BackupCallbackHandler.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d3ddb18feb39077fd2979b0fecc9e65dcd8b1837
--- /dev/null
+++ b/Sources/AppCore/BackupCallbackHandler/BackupCallbackHandler.swift
@@ -0,0 +1,45 @@
+import XXClient
+import Foundation
+import XXMessengerClient
+import XCTestDynamicOverlay
+
+public struct BackupCallbackHandler {
+  public typealias OnError = (Error) -> Void
+
+  public var run: (@escaping OnError) -> Cancellable
+
+  public func callAsFunction(onError: @escaping OnError) -> Cancellable {
+    run(onError)
+  }
+}
+
+extension BackupCallbackHandler {
+  public static func live(
+    messenger: Messenger
+  ) -> BackupCallbackHandler {
+    BackupCallbackHandler { onError in
+      let callback = UpdateBackupFunc { data in
+        do {
+          let url = try FileManager.default.url(
+            for: .applicationSupportDirectory,
+            in: .userDomainMask,
+            appropriateFor: nil,
+            create: true
+          )
+            .appendingPathComponent("backup")
+            .appendingPathExtension("xxm")
+          try data.write(to: url)
+        } catch {
+          onError(error)
+        }
+      }
+      return messenger.registerBackupCallback(callback)
+    }
+  }
+}
+
+extension BackupCallbackHandler {
+  public static let unimplemented = BackupCallbackHandler(
+    run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {})
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManagerMakeDB.swift b/Sources/AppCore/DBManager/DBManagerMakeDB.swift
index 4376f12fb3e5630ce0f9d05cd27474b9dd75515c..a3e514ae75ae674e9bf6a10f951fbd4957b6c72e 100644
--- a/Sources/AppCore/DBManager/DBManagerMakeDB.swift
+++ b/Sources/AppCore/DBManager/DBManagerMakeDB.swift
@@ -21,7 +21,7 @@ extension DBManagerMakeDB {
         .createDirectory(at: url, withIntermediateDirectories: true)
 
       let dbFilePath = url
-        .appendingPathComponent("db")
+        .appendingPathComponent("xxm_database")
         .appendingPathExtension("sqlite")
         .path
 
diff --git a/Sources/AppCore/Logger/Logger.swift b/Sources/AppCore/Logger/Logger.swift
index fbb48f0d2dff23711420e5d7bf80bc3c8a160198..60fc7bf3a56e55125324c3142dea8310e5aa027e 100644
--- a/Sources/AppCore/Logger/Logger.swift
+++ b/Sources/AppCore/Logger/Logger.swift
@@ -4,6 +4,7 @@ import XCTestDynamicOverlay
 
 public struct Logger {
   public enum Message: Equatable {
+    case info(String)
     case error(NSError)
   }
 
@@ -24,6 +25,13 @@ extension Logger {
     let logger = Logging.Logger(label: "xx.messenger")
     return Logger { msg, file, function, line in
       switch msg {
+      case .info(let text):
+        logger.info(
+          .init(stringLiteral: text),
+          file: file,
+          function: function,
+          line: line
+        )
       case .error(let error):
         logger.error(
           .init(stringLiteral: error.localizedDescription),
diff --git a/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift b/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift
index 70fbace772986d506de4ee2338445a7c656bae8e..8103b2674704e57f682006e6e23cd4f263fa8bca 100644
--- a/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift
+++ b/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift
@@ -1,8 +1,8 @@
-import Foundation
-import XCTestDynamicOverlay
+import XXModels
 import XXClient
+import Foundation
 import XXMessengerClient
-import XXModels
+import XCTestDynamicOverlay
 
 public struct MessageListenerHandler {
   public typealias OnError = (Error) -> Void
@@ -32,6 +32,7 @@ extension MessageListenerHandler {
             status: .received,
             isUnread: true,
             text: payload.text,
+            replyMessageId: payload.replyingTo,
             roundURL: message.roundURL
           ))
         } catch {
diff --git a/Sources/AppCore/Models/MessagePayload.swift b/Sources/AppCore/Models/MessagePayload.swift
index 67fb94d905b06ad25816ca8c4d11081c72053f19..7ae774337944fdb62b7c5b862cfdd28d7a3a3295 100644
--- a/Sources/AppCore/Models/MessagePayload.swift
+++ b/Sources/AppCore/Models/MessagePayload.swift
@@ -1,16 +1,22 @@
 import Foundation
 
 public struct MessagePayload: Equatable {
-  public init(text: String) {
+  public init(
+    text: String,
+    replyingTo: Data? = nil
+  ) {
     self.text = text
+    self.replyingTo = replyingTo
   }
 
   public var text: String
+  public var replyingTo: Data?
 }
 
 extension MessagePayload: Codable {
   enum CodingKeys: String, CodingKey {
     case text
+    case replyingTo
   }
 
   public static func decode(_ data: Data) throws -> Self {
diff --git a/Sources/AppCore/NetworkMonitor/GetNetworkConnType.swift b/Sources/AppCore/NetworkMonitor/GetNetworkConnType.swift
new file mode 100644
index 0000000000000000000000000000000000000000..99b460f76069535017a7cb730c3def9e3888bcf6
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitor/GetNetworkConnType.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct GetNetworkConnType {
+  public init(run: @escaping () -> NetworkMonitor.ConnType) {
+    self.run = run
+  }
+
+  public var run: () -> NetworkMonitor.ConnType
+
+  public func callAsFunction() -> NetworkMonitor.ConnType {
+    run()
+  }
+}
+
+extension GetNetworkConnType {
+  public static let unimplemented = GetNetworkConnType(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitor/GetNetworkStatus.swift b/Sources/AppCore/NetworkMonitor/GetNetworkStatus.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e8d6cfb053ccfb6801e206d2f6beb6976d157e29
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitor/GetNetworkStatus.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct GetNetworkStatus {
+  public init(run: @escaping () -> NetworkMonitor.Status) {
+    self.run = run
+  }
+
+  public var run: () -> NetworkMonitor.Status
+
+  public func callAsFunction() -> NetworkMonitor.Status {
+    run()
+  }
+}
+
+extension GetNetworkStatus {
+  public static let unimplemented = GetNetworkStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift b/Sources/AppCore/NetworkMonitor/NetworkMonitor.swift
similarity index 60%
rename from Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift
rename to Sources/AppCore/NetworkMonitor/NetworkMonitor.swift
index e77d4c63087711bff028f6cd78f1b896b399a888..db79b79d26f877fbd3b04470378a4d434f2e6cfd 100644
--- a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift
+++ b/Sources/AppCore/NetworkMonitor/NetworkMonitor.swift
@@ -1,7 +1,7 @@
 import Combine
 import Network
 
-public struct NetworkMonitorManager {
+public struct NetworkMonitor {
   public enum Status: Equatable {
     case unknown
     case available
@@ -15,14 +15,15 @@ public struct NetworkMonitorManager {
     case cellular
   }
 
-  public var start: NetworkMonitorStart
-  public var update: NetworkMonitorUpdate
-  public var status: NetworkMonitorStatus
-  public var connType: NetworkMonitorConnType
+  public var start: StartNetworkMonitor
+  public var update: UpdateNetworkStatus
+  public var getStatus: GetNetworkStatus
+  public var connType: GetNetworkConnType
+  public var observeStatus: ObserveNetworkStatus
 }
 
-extension NetworkMonitorManager {
-  public static func live() -> NetworkMonitorManager {
+extension NetworkMonitor {
+  public static func live() -> NetworkMonitor {
     class Context {
       var monitor = NWPathMonitor()
       let xxAvailability = CurrentValueSubject<Bool?, Never>(nil)
@@ -54,7 +55,7 @@ extension NetworkMonitorManager {
       update: .init {
         context.xxAvailability.send($0)
       },
-      status: .init {
+      getStatus: .init {
         guard let xxAvailability = context.xxAvailability.value else {
           return .xxNotAvailable
         }
@@ -62,16 +63,34 @@ extension NetworkMonitorManager {
       },
       connType: .init {
         context.currentConnType.value
+      },
+      observeStatus: .init {
+        context
+          .internetAvailability
+          .combineLatest(context.xxAvailability)
+          .map { (internet, xx) -> Status in
+            guard let internet, let xx else { return .unknown}
+            switch (internet, xx) {
+            case (true, true):
+              return .available
+            case (true, false):
+              return .xxNotAvailable
+            case (false, _):
+              return .internetNotAvailable
+            }
+          }.removeDuplicates()
+          .eraseToAnyPublisher()
       }
     )
   }
 }
 
-extension NetworkMonitorManager {
-  public static let unimplemented = NetworkMonitorManager(
+extension NetworkMonitor {
+  public static let unimplemented = NetworkMonitor(
     start: .unimplemented,
     update: .unimplemented,
-    status: .unimplemented,
-    connType: .unimplemented
+    getStatus: .unimplemented,
+    connType: .unimplemented,
+    observeStatus: .unimplemented
   )
 }
diff --git a/Sources/AppCore/NetworkMonitor/ObserveNetworkStatus.swift b/Sources/AppCore/NetworkMonitor/ObserveNetworkStatus.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f6df5d96ebc6f4b243fbd8afa84aa5f45c39bec6
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitor/ObserveNetworkStatus.swift
@@ -0,0 +1,20 @@
+import Combine
+import XCTestDynamicOverlay
+
+public struct ObserveNetworkStatus {
+  public init(run: @escaping () -> AnyPublisher<NetworkMonitor.Status, Never>) {
+    self.run = run
+  }
+
+  public var run: () -> AnyPublisher<NetworkMonitor.Status, Never>
+
+  public func callAsFunction() -> AnyPublisher<NetworkMonitor.Status, Never> {
+    run()
+  }
+}
+
+extension ObserveNetworkStatus {
+  public static let unimplemented = ObserveNetworkStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift b/Sources/AppCore/NetworkMonitor/StartNetworkMonitor.swift
similarity index 65%
rename from Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift
rename to Sources/AppCore/NetworkMonitor/StartNetworkMonitor.swift
index 4bb08bdbdd23a28b04c3b7f1a13bfbf53995e0a1..6fa6e45a7f79d810d9ae341293cb44761e03cbb5 100644
--- a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift
+++ b/Sources/AppCore/NetworkMonitor/StartNetworkMonitor.swift
@@ -1,6 +1,6 @@
 import XCTestDynamicOverlay
 
-public struct NetworkMonitorStart {
+public struct StartNetworkMonitor {
   public init(run: @escaping () -> Void) {
     self.run = run
   }
@@ -12,8 +12,8 @@ public struct NetworkMonitorStart {
   }
 }
 
-extension NetworkMonitorStart {
-  public static let unimplemented = NetworkMonitorStart(
+extension StartNetworkMonitor {
+  public static let unimplemented = StartNetworkMonitor(
     run: XCTUnimplemented("\(Self.self)")
   )
 }
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift b/Sources/AppCore/NetworkMonitor/UpdateNetworkStatus.swift
similarity index 67%
rename from Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift
rename to Sources/AppCore/NetworkMonitor/UpdateNetworkStatus.swift
index 6659aad330ce06f45306cd484c24835d67d83e30..825945096def2084b6bd9c135bba04291ec60a53 100644
--- a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift
+++ b/Sources/AppCore/NetworkMonitor/UpdateNetworkStatus.swift
@@ -1,6 +1,6 @@
 import XCTestDynamicOverlay
 
-public struct NetworkMonitorUpdate {
+public struct UpdateNetworkStatus {
   public init(run: @escaping (Bool) -> Void) {
     self.run = run
   }
@@ -12,8 +12,8 @@ public struct NetworkMonitorUpdate {
   }
 }
 
-extension NetworkMonitorUpdate {
-  public static let unimplemented = NetworkMonitorUpdate(
+extension UpdateNetworkStatus {
+  public static let unimplemented = UpdateNetworkStatus(
     run: XCTUnimplemented("\(Self.self)")
   )
 }
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift
deleted file mode 100644
index 8340f33fd448d9dfd87d76c30dc736a452375c38..0000000000000000000000000000000000000000
--- a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import XCTestDynamicOverlay
-
-public struct NetworkMonitorConnType {
-  public init(run: @escaping () -> NetworkMonitorManager.ConnType) {
-    self.run = run
-  }
-
-  public var run: () -> NetworkMonitorManager.ConnType
-
-  public func callAsFunction() -> NetworkMonitorManager.ConnType {
-    run()
-  }
-}
-
-extension NetworkMonitorConnType {
-  public static let unimplemented = NetworkMonitorConnType(
-    run: XCTUnimplemented("\(Self.self)")
-  )
-}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift
deleted file mode 100644
index afc3169ce97622e94ec6bf74259512cc3e378d44..0000000000000000000000000000000000000000
--- a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import XCTestDynamicOverlay
-
-public struct NetworkMonitorStatus {
-  public init(run: @escaping () -> NetworkMonitorManager.Status) {
-    self.run = run
-  }
-
-  public var run: () -> NetworkMonitorManager.Status
-
-  public func callAsFunction() -> NetworkMonitorManager.Status {
-    run()
-  }
-}
-
-extension NetworkMonitorStatus {
-  public static let unimplemented = NetworkMonitorStatus(
-    run: XCTUnimplemented("\(Self.self)")
-  )
-}
diff --git a/Sources/AppCore/RootViewController.swift b/Sources/AppCore/RootViewController.swift
index eb7db899e63a9c1687ba4b9d6ab22f9abbf58a62..5082447d2980bda881d3c8094ea10a721a638c85 100644
--- a/Sources/AppCore/RootViewController.swift
+++ b/Sources/AppCore/RootViewController.swift
@@ -1,11 +1,10 @@
 import UIKit
 import Combine
-import StatusBarFeature
-import ComposableArchitecture
+import Dependencies
 
 public final class RootViewController: UIViewController {
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
   @Dependency(\.app.hudManager) var hudManager: HUDManager
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
   @Dependency(\.app.toastManager) var toastManager: ToastManager
   
   var hud: HUDView?
@@ -24,7 +23,7 @@ public final class RootViewController: UIViewController {
   required init?(coder: NSCoder) { nil }
   
   public override var preferredStatusBarStyle: UIStatusBarStyle  {
-    statusBar.current()
+    statusBar.get()
   }
   
   public override func viewDidLoad() {
@@ -73,8 +72,6 @@ public final class RootViewController: UIViewController {
   }
 }
 
-// MARK: - Toaster
-
 extension RootViewController {
   @objc private func didPanToast(_ sender: UIPanGestureRecognizer) {
     guard let toastView = sender.view else { return }
@@ -167,8 +164,6 @@ extension RootViewController {
   }
 }
 
-// MARK: - HUD
-
 extension RootViewController {
   private func add(hudView: HUDView) {
     if let hud {
@@ -196,62 +191,4 @@ extension RootViewController {
     
     hud = hudView
   }
-  
-  //    if statusSubject.value.isPresented == true && status.isPresented == true {
-  //      self.errorView = nil
-  //      self.animation = nil
-  //      self.window = nil
-  //      self.actionButton = nil
-  //      self.titleLabel = nil
-  //
-  //      switch status {
-  //      case .on:
-  //        animation = DotAnimation()
-  //
-  //      case .onTitle(let text):
-  //        animation = DotAnimation()
-  //        titleLabel = UILabel()
-  //        titleLabel!.text = text
-  //
-  //      case .onAction(let title):
-  //        animation = DotAnimation()
-  //        actionButton = CapsuleButton()
-  //        actionButton!.set(style: .seeThroughWhite, title: title)
-  //
-  //      case .error(let error):
-  //        errorView = ErrorView(with: error)
-  //      case .none:
-  //        break
-  //      }
-  //
-  //      showWindow()
-  //    }
-  
-  //    if statusSubject.value.isPresented == false && status.isPresented == true {
-  //        switch status {
-  //        case .on:
-  //          animation = DotAnimation()
-  //
-  //        case .onTitle(let text):
-  //          animation = DotAnimation()
-  //          titleLabel = UILabel()
-  //          titleLabel!.text = text
-  //
-  //        case .onAction(let title):
-  //          animation = DotAnimation()
-  //          actionButton = CapsuleButton()
-  //          actionButton!.set(style: .seeThroughWhite, title: title)
-  //
-  //        case .error(let error):
-  //          errorView = ErrorView(with: error)
-  //        case .none:
-  //          break
-  //        }
-  //
-  //        showWindow()
-  //    }
-  
-  //    if statusSubject.value.isPresented == true && status.isPresented == false {
-  //        hideWindow()
-  //    }
 }
diff --git a/Sources/AppCore/SendMessage/SendMessage.swift b/Sources/AppCore/SendMessage/SendMessage.swift
index f675dc0d2322cbe3b7611d92823eece9b5420d42..d8ad8813c09b85fc9a6c33ef674680cb8943a2a3 100644
--- a/Sources/AppCore/SendMessage/SendMessage.swift
+++ b/Sources/AppCore/SendMessage/SendMessage.swift
@@ -8,15 +8,16 @@ public struct SendMessage {
   public typealias OnError = (Error) -> Void
   public typealias Completion = () -> Void
 
-  public var run: (String, Data, @escaping OnError, @escaping Completion) -> Void
+  public var run: (String, Data?, Data, @escaping OnError, @escaping Completion) -> Void
 
   public func callAsFunction(
     text: String,
+    replyingTo: Data?,
     to recipientId: Data,
     onError: @escaping OnError,
     completion: @escaping Completion
   ) {
-    run(text, recipientId, onError, completion)
+    run(text, replyingTo, recipientId, onError, completion)
   }
 }
 
@@ -26,7 +27,7 @@ extension SendMessage {
     db: DBManagerGetDB,
     now: @escaping () -> Date
   ) -> SendMessage {
-    SendMessage { text, recipientId, onError, completion in
+    SendMessage { text, replyingTo, recipientId, onError, completion in
       do {
         let myContactId = try messenger.e2e.tryGet().getContact().getId()
         let message = try db().saveMessage(.init(
@@ -36,9 +37,10 @@ extension SendMessage {
           date: now(),
           status: .sending,
           isUnread: false,
-          text: text
+          text: text,
+          replyMessageId: replyingTo
         ))
-        let payload = MessagePayload(text: message.text)
+        let payload = MessagePayload(text: message.text, replyingTo: replyingTo)
         let report = try messenger.sendMessage(
           recipientId: recipientId,
           payload: try payload.encode(),
diff --git a/Sources/AppCore/StatusBar/StatusBarStylist.swift b/Sources/AppCore/StatusBar/StatusBarStylist.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7eaa87fdcf0db2ac136179bcc86b11cd718fd7c9
--- /dev/null
+++ b/Sources/AppCore/StatusBar/StatusBarStylist.swift
@@ -0,0 +1,59 @@
+import UIKit
+import Combine
+import XCTestDynamicOverlay
+
+public struct StatusBarStylist {
+  public var set: SetStyle
+  public var get: GetStyle
+  public var observe: ObserveStyle
+
+  public static func live() -> StatusBarStylist {
+    let styleSubject = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
+    return .init(
+      set: .init { styleSubject.send($0) },
+      get: .init { styleSubject.value },
+      observe: .init { styleSubject.eraseToAnyPublisher() }
+    )
+  }
+  public static let unimplemented = StatusBarStylist(
+    set: .unimplemented,
+    get: .unimplemented,
+    observe: .unimplemented
+  )
+}
+
+public struct GetStyle {
+  public var run: () -> UIStatusBarStyle
+
+  public func callAsFunction() -> UIStatusBarStyle {
+    run()
+  }
+
+  public static let unimplemented = GetStyle(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct SetStyle {
+  public var run: (UIStatusBarStyle) -> Void
+
+  public func callAsFunction(_ style: UIStatusBarStyle) -> Void {
+    run(style)
+  }
+
+  public static let unimplemented = SetStyle(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct ObserveStyle {
+  public var run: () -> AnyPublisher<UIStatusBarStyle, Never>
+
+  public func callAsFunction() -> AnyPublisher<UIStatusBarStyle, Never> {
+    run()
+  }
+
+  public static let unimplemented = ObserveStyle(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppFeature/AppDelegate.swift b/Sources/AppFeature/AppDelegate.swift
index c4dc80dab5df9e71b580a6e7525fd90858c0d414..7cc572aa26a9f469c6787c4927b29da6b821df77 100644
--- a/Sources/AppFeature/AppDelegate.swift
+++ b/Sources/AppFeature/AppDelegate.swift
@@ -1,224 +1,19 @@
 import UIKit
-import BackgroundTasks
-
-import Shared
-import Defaults
-import PushFeature
+import AppCore
 import LaunchFeature
-import CrashReporting
-import DI
-
-import XXModels
-import XXLogger
-import XXClient
-import Navigation
-import XXMessengerClient
-
-import CloudFiles
-import CloudFilesDrive
-import CloudFilesICloud
-import CloudFilesDropbox
 
 public class AppDelegate: UIResponder, UIApplicationDelegate {
-  @Dependency var navigator: Navigator
-  @Dependency var pushRouter: PushRouter
-  @Dependency var pushHandler: PushHandling
-  @Dependency var crashReporter: CrashReporter
-
-  @KeyObject(.hideAppList, defaultValue: false) var hideAppList: Bool
-  @KeyObject(.recordingLogs, defaultValue: true) var recordingLogs: Bool
-  @KeyObject(.crashReporting, defaultValue: true) var isCrashReportingEnabled: Bool
-
-  var calledStopNetwork = false
-  var forceFailedPendingMessages = false
-
-  var coverView: UIView?
-  var backgroundTimer: Timer?
   public var window: UIWindow?
 
   public func application(
     _ application: UIApplication,
     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
   ) -> Bool {
-    UNUserNotificationCenter.current().delegate = self
-    setupCloudFilesManagers()
-    setupCrashReporting()
-    setupLogging()
 
     let navController = UINavigationController(rootViewController: LaunchController())
-    let rootViewController = RootViewController(navController)
     window = UIWindow(frame: UIScreen.main.bounds)
-    window?.rootViewController = rootViewController
+    window?.rootViewController = RootViewController(navController)
     window?.makeKeyAndVisible()
-
-    DependencyRegistrator.registerNavigators(navController)
-
-    DI.Container.shared.register(
-      PushRouter.live(navigationController: navController)
-    )
     return true
   }
-
-  public func application(application: UIApplication, shouldAllowExtensionPointIdentifier: String) -> Bool {
-    false
-  }
-
-  public func applicationDidEnterBackground(_ application: UIApplication) {
-    if let messenger = try? DI.Container.shared.resolve() as Messenger,
-       let database = try? DI.Container.shared.resolve() as Database,
-       let cMix = try? messenger.cMix.tryGet() {
-      let backgroundTask = application.beginBackgroundTask(withName: "xx.stop.network") {}
-
-      backgroundTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { timer in
-        print(">>> .backgroundTimeRemaining: \(UIApplication.shared.backgroundTimeRemaining)")
-
-        guard UIApplication.shared.backgroundTimeRemaining > 8 else {
-          if !self.calledStopNetwork {
-            self.calledStopNetwork = true
-            try! messenger.stop()
-            print(">>> Called stopNetworkFollower")
-          } else {
-            if cMix.hasRunningProcesses() == false {
-              application.endBackgroundTask(backgroundTask)
-              timer.invalidate()
-            }
-          }
-
-          return
-        }
-
-        guard UIApplication.shared.backgroundTimeRemaining > 9 else {
-          if !self.forceFailedPendingMessages {
-            self.forceFailedPendingMessages = true
-            let query = Message.Query(status: [.sending])
-            let assignment = Message.Assignments(status: .sendingFailed)
-            _ = try? database.bulkUpdateMessages(query, assignment)
-          }
-          return
-        }
-      })
-    }
-  }
-
-  public func applicationWillResignActive(_ application: UIApplication) {
-    if hideAppList {
-      coverView?.removeFromSuperview()
-      coverView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
-      coverView?.frame = window?.bounds ?? .zero
-      window?.addSubview(coverView!)
-    }
-  }
-
-  public func applicationWillTerminate(_ application: UIApplication) {
-    if let messenger = try? DI.Container.shared.resolve() as Messenger {
-      try? messenger.stop()
-    }
-  }
-
-  public func applicationWillEnterForeground(_ application: UIApplication) {
-    if backgroundTimer != nil {
-      backgroundTimer?.invalidate()
-      backgroundTimer = nil
-      print(">>> Invalidated background timer")
-    }
-
-    if let messenger = try? DI.Container.shared.resolve() as Messenger,
-       let cMix = messenger.cMix.get() {
-      guard self.calledStopNetwork == true else { return }
-      try? cMix.startNetworkFollower(timeoutMS: 10_000)
-      print(">>> Called startNetworkFollower")
-      self.calledStopNetwork = false
-    }
-  }
-
-  public func applicationDidBecomeActive(_ application: UIApplication) {
-    application.applicationIconBadgeNumber = 0
-    coverView?.removeFromSuperview()
-  }
-
-  public func application(
-    _ app: UIApplication,
-    open url: URL,
-    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
-  ) -> Bool {
-    handleRedirectURL(url)
-  }
-
-  public func application(
-    _ application: UIApplication,
-    continue userActivity: NSUserActivity,
-    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
-  ) -> Bool {
-    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
-          let incomingURL = userActivity.webpageURL,
-          let username = getUsernameFromInvitationDeepLink(incomingURL),
-          let router = try? DI.Container.shared.resolve() as PushRouter else {
-      return false
-    }
-
-    router.navigateTo(.search(username: username), {})
-    return true
-  }
-}
-
-extension AppDelegate: UNUserNotificationCenterDelegate {
-  public func userNotificationCenter(
-    _ center: UNUserNotificationCenter,
-    didReceive response: UNNotificationResponse,
-    withCompletionHandler completionHandler: @escaping () -> Void
-  ) {
-    let userInfo = response.notification.request.content.userInfo
-    pushHandler.handleAction(pushRouter, userInfo, completionHandler)
-  }
-
-  public func application(
-    _ application: UIApplication,
-    didReceiveRemoteNotification notification: [AnyHashable: Any],
-    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
-  ) {
-    pushHandler.handlePush(notification, completionHandler)
-  }
-
-  public func application(
-    _: UIApplication,
-    didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
-  ) {
-    pushHandler.registerToken(deviceToken)
-  }
-}
-
-extension AppDelegate {
-  private func setupCrashReporting() {
-    crashReporter.configure()
-    crashReporter.setEnabled(isCrashReportingEnabled)
-  }
-
-  private func setupCloudFilesManagers() {
-    CloudFilesManager.all[.icloud] = .iCloud(fileName: "backup.xxm")
-    CloudFilesManager.all[.dropbox] = .dropbox(appKey: "ppx0de5f16p9aq2", path: "/backup/backup.xxm")
-    CloudFilesManager.all[.drive] = .drive(
-      apiKey: "AIzaSyCbI2yQ7pbuVSRvraqanjGcS9CDrjD7lNU",
-      clientId: "662236151640-herpu89qikpfs9m4kvbi9bs5fpdji5de.apps.googleusercontent.com",
-      fileName: "backup.xxm"
-    )
-  }
-
-  private func setupLogging() {
-    if recordingLogs {
-      XXLogger.start()
-    }
-  }
-}
-
-func getUsernameFromInvitationDeepLink(_ url: URL) -> String? {
-  if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
-     components.scheme == "https",
-     components.host == "elixxir.io",
-     components.path == "/connect",
-     let queryItem = components.queryItems?.first(where: { $0.name == "username" }),
-     let username = queryItem.value {
-    return username
-  }
-
-  return nil
 }
diff --git a/Sources/AppFeature/DependencyRegistrator.swift b/Sources/AppFeature/DependencyRegistrator.swift
index cd4baf2baf6b1af0cb2946df7c72f45a41437c96..ed05ba40e4225ee6ce3345aca596276c3fc2915e 100644
--- a/Sources/AppFeature/DependencyRegistrator.swift
+++ b/Sources/AppFeature/DependencyRegistrator.swift
@@ -8,18 +8,14 @@ import MobileCoreServices
 // MARK: Isolated features
 
 import Bindings
-import XXLogger
 import Keychain
 import Defaults
 import Voxophone
-import Permissions
 import PushFeature
-import CrashService
 import CrashReporting
 import VersionChecking
 import ReportingFeature
 import CountryListFeature
-import DI
 
 // MARK: UI Features
 
@@ -33,246 +29,131 @@ import SearchFeature
 import LaunchFeature
 import RestoreFeature
 import ContactFeature
+import WebsiteFeature
 import ProfileFeature
 import ChatListFeature
 import SettingsFeature
 import RequestsFeature
+import GroupDraftFeature
 import OnboardingFeature
+import CreateGroupFeature
 import ContactListFeature
+import RequestPermissionFeature
 
 import Shared
 import XXClient
-import Navigation
+import AppNavigation
 import KeychainAccess
 import XXMessengerClient
 
 import ComposableArchitecture
 
-struct DependencyRegistrator {
-  static public func registerNavigators(_ navController: UINavigationController) {
-//    container.register(CombinedNavigator(
-//      PresentModalNavigator(),
-//      DismissModalNavigator(),
-//      PushNavigator(),
-//      PopToRootNavigator(),
-//      PopToNavigator(),
-//      SetStackNavigator(),
-//
-//      OpenUpNavigator(),
-//      OpenLeftNavigator(),
-//
-//      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 }
-//      ),
-//      PresentDrawerNavigator(
-//        screen: DrawerController.init(_:),
-//        navigationController: { navController }
-//      ),
-//      PresentContactListNavigator(
-//        screen: ContactListController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentMenuNavigator(
-//        screen: MenuController.init(_:),
-//        navigationController: { navController }
-//      ),
-//      PresentScanNavigator(
-//        screen: ScanContainerController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentNewGroupNavigator(
-//        screen: CreateGroupController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentCountryListNavigator(
-//        screen: CountryListController.init(_:),
-//        navigationController: { navController }
-//      ),
-//      PresentProfileNavigator(
-//        screen: ProfileController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentSettingsNavigator(
-//        screen: SettingsController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentSettingsAdvancedNavigator(
-//        screen: SettingsAdvancedController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentSettingsBackupNavigator(
-//        screen: BackupController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentSettingsAccountDeleteNavigator(
-//        screen: AccountDeleteController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentContactNavigator(
-//        screen: ContactController.init(_:),
-//        navigationController: { navController }
-//      ),
-//      PresentActivitySheetNavigator(
-//        screen: { UIActivityViewController(
-//          activityItems: $0,
-//          applicationActivities: nil
-//        )},
-//        navigationController: { navController }
-//      ),
-//      PresentProfileEmailNavigator(
-//        screen: ProfileEmailController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentProfilePhoneNavigator(
-//        screen: ProfilePhoneController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentPermissionRequestNavigator(
-//        screen: RequestPermissionController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentPhotoLibraryNavigator(
-//        screen: UIImagePickerController.init,
-//        navigationController: { navController }
-//      ),
-//      PresentProfileCodeNavigator(
-//        screen: ProfileCodeController.init(_:_:_:),
-//        navigationController: { navController }
-//      )
-//    ) as Navigator)
-  }
-}
+extension NavigatorKey: DependencyKey {
+  public static let liveValue: Navigator = CombinedNavigator(
+    PresentModalNavigator(),
+    DismissModalNavigator(),
+    PushNavigator(),
+    PopToRootNavigator(),
+    PopToNavigator(),
+    SetStackNavigator(),
+    OpenUpNavigator(),
+    OpenLeftNavigator(),
 
-public struct OtherDependencies {
-  public var voxophone: Voxophone
-  public var sendReport: SendReport
-  public var pushHandler: PushHandler
-  public var versionCheck: VersionCheck
-  public var backupService: BackupService
-  public var hudController: HUDController
-  public var crashReporter: CrashReporter
-  public var networkMonitor: NetworkMonitor
-  public var keyObjectStore: KeyObjectStore
-  public var fetchBannedList: FetchBannedList
-  public var toastController: ToastController
-  public var reportingStatus: ReportingStatus
-  public var keychainHandler: KeychainHandler
-  public var makeReportDrawer: MakeReportDrawer
-  public var statusBarStylist: StatusBarStylist
-  public var getIdFromContact: GetIdFromContact
-  public var permissionHandler: PermissionHandler
-  public var processBannedList: ProcessBannedList
-  public var makeAppScreenshot: MakeAppScreenshot
-  public var getFactsFromContact: GetFactsFromContact
-}
+    PresentPhotoLibraryNavigator(),
+    PresentActivitySheetNavigator(),
 
-extension OtherDependencies {
-  public static func live() -> OtherDependencies {
-    .init(
-      voxophone: .init(),
-      sendReport: .live,
-      pushHandler: .init(),
-      versionCheck: .live,
-      backupService: .init(),
-      hudController: .init(),
-      crashReporter: .live,
-      networkMonitor: .init(),
-      keyObjectStore: .userDefaults,
-      fetchBannedList: .live,
-      toastController: .init(),
-      reportingStatus: .live(),
-      keychainHandler: .init(),
-      makeReportDrawer: .live,
-      statusBarStylist: .init(),
-      getIdFromContact: .live,
-      permissionHandler: .init(),
-      processBannedList: .live,
-      makeAppScreenshot: .live,
-      getFactsFromContact: .live
+    PresentWebsiteNavigator(
+      WebsiteController.init(_:)
+    ),
+    PresentCreateGroupNavigator(
+      CreateGroupController.init(_:)
+    ),
+    PresentGroupDraftNavigator(
+      GroupDraftController.init
+    ),
+    PresentMenuNavigator(
+      MenuController.init(_:_:)
+    ),
+    PresentProfileNavigator(
+      ProfileController.init
+    ),
+    PresentChatListNavigator(
+      ChatListController.init
+    ),
+    PresentDrawerNavigator(
+      DrawerController.init(_:)
+    ),
+    PresentScanNavigator(
+      ScanContainerController.init
+    ),
+    PresentChatNavigator(
+      SingleChatController.init(_:)
+    ),
+    PresentContactNavigator(
+      ContactController.init(_:)
+    ),
+    PresentSettingsNavigator(
+      SettingsMainController.init
+    ),
+    PresentSettingsBackupNavigator(
+      BackupController.init
+    ),
+    PresentRestoreListNavigator(
+      RestoreListController.init
+    ),
+    PresentContactListNavigator(
+      ContactListController.init
+    ),
+    PresentGroupChatNavigator(
+      GroupChatController.init(_:)
+    ),
+    PresentProfileEmailNavigator(
+      ProfileEmailController.init
+    ),
+    PresentProfilePhoneNavigator(
+      ProfilePhoneController.init
+    ),
+    PresentSearchNavigator(
+      SearchContainerController.init(_:)
+    ),
+    PresentRequestsNavigator(
+      RequestsContainerController.init
+    ),
+    PresentCountryListNavigator(
+      CountryListController.init(_:)
+    ),
+    PresentOnboardingEmailNavigator(
+      OnboardingEmailController.init
+    ),
+    PresentOnboardingPhoneNavigator(
+      OnboardingPhoneController.init
+    ),
+    PresentProfileCodeNavigator(
+      ProfileCodeController.init(_:_:_:)
+    ),
+    PresentOnboardingStartNavigator(
+      OnboardingStartController.init
+    ),
+    PresentSettingsAdvancedNavigator(
+      SettingsAdvancedController.init
+    ),
+    PresentTermsAndConditionsNavigator(
+      TermsConditionsController.init
+    ),
+    PresentPermissionRequestNavigator(
+      RequestPermissionController.init
+    ),
+    PresentOnboardingWelcomeNavigator(
+      OnboardingWelcomeController.init
+    ),
+    PresentSettingsAccountDeleteNavigator(
+      SettingsDeleteController.init
+    ),
+    PresentOnboardingUsernameNavigator(
+      OnboardingUsernameController.init
+    ),
+    PresentOnboardingCodeNavigator(
+      OnboardingCodeController.init(_:_:_:)
     )
-  }
-
-  public static let unimplemented = OtherDependencies(
-    voxophone: .init(),
-    sendReport: .unimplemented,
-    pushHandler: .init(),
-    versionCheck: .unimplemented,
-    backupService: .init(),
-    hudController: .init(),
-    crashReporter: .noop,
-    networkMonitor: .init(),
-    keyObjectStore: .mock(dictionary: [:]),
-    fetchBannedList: .unimplemented,
-    toastController: .init(),
-    reportingStatus: .mock(),
-    keychainHandler: .init(),
-    makeReportDrawer: .unimplemented,
-    statusBarStylist: .init(),
-    getIdFromContact: .live,
-    permissionHandler: .init(),
-    processBannedList: .unimplemented,
-    makeAppScreenshot: .unimplemented,
-    getFactsFromContact: .live
   )
 }
-
-private enum OtherDependenciesKey: DependencyKey {
-  static let liveValue: OtherDependencies = .live()
-  static let testValue: OtherDependencies = .unimplemented
-}
-
-extension DependencyValues {
-  public var others: OtherDependencies {
-    get { self[OtherDependenciesKey.self] }
-    set { self[OtherDependenciesKey.self] = newValue }
-  }
-}
diff --git a/Sources/AppFeature/PushRouter.swift b/Sources/AppFeature/PushRouter.swift
index dc790bd8d3af5923dd99ea87e3b051adcf840bad..f36d1e8ab7c9167800fa4557dc3d6fd2b65956a4 100644
--- a/Sources/AppFeature/PushRouter.swift
+++ b/Sources/AppFeature/PushRouter.swift
@@ -1,4 +1,3 @@
-import DI
 import UIKit
 import XXModels
 import PushFeature
@@ -11,47 +10,48 @@ import XXMessengerClient
 
 extension PushRouter {
   static func live(navigationController: UINavigationController) -> PushRouter {
-    PushRouter { route, completion in
-      if let launchController = navigationController.viewControllers.last as? LaunchController {
-        launchController.pendingPushRoute = route
-      } else {
-        switch route {
-        case .requests:
-          if !(navigationController.viewControllers.last is RequestsContainerController) {
-            navigationController.setViewControllers([RequestsContainerController()], animated: true)
-          }
-        case .search(username: let username):
-          if let messenger = try? DI.Container.shared.resolve() as Messenger,
-             let _ = try? messenger.ud.get()?.getContact() {
-            if !(navigationController.viewControllers.last is SearchContainerController) {
-              navigationController.setViewControllers([
-                ChatListController(),
-                SearchContainerController(username)
-              ], animated: true)
-            } else {
-              (navigationController.viewControllers.last as? SearchContainerController)?.startSearchingFor(username)
-            }
-          }
-        case .contactChat(id: let id):
-          if let database: Database = try? DI.Container.shared.resolve(),
-             let contact = try? database.fetchContacts(.init(id: [id])).first {
-            navigationController.setViewControllers([
-              ChatListController(),
-              SingleChatController(contact)
-            ], animated: true)
-          }
-        case .groupChat(id: let id):
-          if let database: Database = try? DI.Container.shared.resolve(),
-             let info = try? database.fetchGroupInfos(.init(groupId: id)).first {
-            navigationController.setViewControllers([
-              ChatListController(),
-              GroupChatController(info)
-            ], animated: true)
-          }
-        }
-      }
-
-      completion()
-    }
+    fatalError()
+//    PushRouter { route, completion in
+//      if let launchController = navigationController.viewControllers.last as? LaunchController {
+//        launchController.pendingPushRoute = route
+//      } else {
+//        switch route {
+//        case .requests:
+//          if !(navigationController.viewControllers.last is RequestsContainerController) {
+//            navigationController.setViewControllers([RequestsContainerController()], animated: true)
+//          }
+//        case .search(username: let username):
+//          if let messenger = try? DI.Container.shared.resolve() as Messenger,
+//             let _ = try? messenger.ud.get()?.getContact() {
+//            if !(navigationController.viewControllers.last is SearchContainerController) {
+//              navigationController.setViewControllers([
+//                ChatListController(),
+//                SearchContainerController(username)
+//              ], animated: true)
+//            } else {
+//              (navigationController.viewControllers.last as? SearchContainerController)?.startSearchingFor(username)
+//            }
+//          }
+//        case .contactChat(id: let id):
+//          if let database: Database = try? DI.Container.shared.resolve(),
+//             let contact = try? dbManager.getDB().fetchContacts(.init(id: [id])).first {
+//            navigationController.setViewControllers([
+//              ChatListController(),
+//              SingleChatController(contact)
+//            ], animated: true)
+//          }
+//        case .groupChat(id: let id):
+//          if let database: Database = try? DI.Container.shared.resolve(),
+//             let info = try? dbManager.getDB().fetchGroupInfos(.init(groupId: id)).first {
+//            navigationController.setViewControllers([
+//              ChatListController(),
+//              GroupChatController(info)
+//            ], animated: true)
+//          }
+//        }
+//      }
+//
+//      completion()
+//    }
   }
 }
diff --git a/Sources/AppNavigation/Action.swift b/Sources/AppNavigation/Action.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ff697eeb21a0937ded7ee2c33961f8cde8592c69
--- /dev/null
+++ b/Sources/AppNavigation/Action.swift
@@ -0,0 +1,2 @@
+/// Navigation action
+public protocol Action {}
diff --git a/Sources/AppNavigation/CombinedNavigator.swift b/Sources/AppNavigation/CombinedNavigator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fdbb1741cfe97da7c9295797f57711bfadf17553
--- /dev/null
+++ b/Sources/AppNavigation/CombinedNavigator.swift
@@ -0,0 +1,30 @@
+/// Combines multiple navigators into a single one
+///
+/// - Action is performed using the first navigator that can handle it
+/// - When there is no navigator that can handle given action, assertion is thrown
+/// - When there are multiple navigators that can handle given action, assertion is thrown
+public struct CombinedNavigator: Navigator {
+  public init(_ navigators: Navigator...) {
+    self.navigators = navigators
+  }
+
+  public init(_ navigators: [Navigator]) {
+    self.navigators = navigators
+  }
+
+  public func perform(_ action: Action, completion: @escaping () -> Void) {
+    let navigators = self.navigators.filter { $0.canPerform(action) }
+    guard let firstNavigator = navigators.first else {
+      assertionFailure("No navigator to perform action: \(action)", #file, #line)
+      return
+    }
+    guard navigators.count == 1 else {
+      assertionFailure("Multiple navigators can perform action: \(action), \(navigators)", #file, #line)
+      return
+    }
+    firstNavigator.perform(action, completion: completion)
+  }
+
+  let navigators: [Navigator]
+  var assertionFailure: (@autoclosure () -> String, StaticString, UInt) -> Void = Swift.assertionFailure
+}
diff --git a/Sources/AppNavigation/CustomTransitions/BottomTransition.swift b/Sources/AppNavigation/CustomTransitions/BottomTransition.swift
new file mode 100644
index 0000000000000000000000000000000000000000..66b422c1f833a2b6690cea8947ee07f9481ba070
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/BottomTransition.swift
@@ -0,0 +1,136 @@
+import UIKit
+import Combine
+
+final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
+  enum Direction {
+    case present
+    case dismiss
+  }
+
+  let isDismissableOnBackground: Bool
+  var direction: Direction = .present
+  private let onDismissal: (() -> Void)?
+  private weak var darkOverlayView: UIControl?
+  private weak var topConstraint: NSLayoutConstraint?
+  private weak var bottomConstraint: NSLayoutConstraint?
+  private var cancellables = Set<AnyCancellable>()
+
+  private var presentedConstraints: [NSLayoutConstraint] = []
+  private var dismissedConstraints: [NSLayoutConstraint] = []
+  private var presentingController: UIViewController?
+
+  init(
+    _ isDismissableOnBackground: Bool = true,
+    onDismissal: (() -> Void)?
+  ) {
+    self.onDismissal = onDismissal
+    self.isDismissableOnBackground = isDismissableOnBackground
+    super.init()
+  }
+
+  func transitionDuration(
+    using context: UIViewControllerContextTransitioning?
+  ) -> TimeInterval { 0.5 }
+
+  func animateTransition(
+    using context: UIViewControllerContextTransitioning
+  ) {
+    switch direction {
+    case .present:
+      present(using: context)
+    case .dismiss:
+      dismiss(using: context)
+    }
+  }
+
+  private func present(using context: UIViewControllerContextTransitioning) {
+    guard let presentingController = context.viewController(forKey: .from),
+          let presentedView = context.view(forKey: .to) else {
+      context.completeTransition(false)
+      return
+    }
+
+    let darkOverlayView = UIControl()
+    self.darkOverlayView = darkOverlayView
+
+    darkOverlayView.alpha = 0.0
+    darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
+    context.containerView.addSubview(darkOverlayView)
+    darkOverlayView.frame = context.containerView.bounds
+
+    if isDismissableOnBackground {
+      darkOverlayView.addTarget(self, action: #selector(didTapOverlay), for: .touchUpInside)
+      self.presentingController = presentingController
+    }
+
+    context.containerView.addSubview(presentedView)
+    presentedView.translatesAutoresizingMaskIntoConstraints = false
+
+    presentedConstraints = [
+      presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
+      presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
+      presentedView.bottomAnchor.constraint(equalTo: context.containerView.bottomAnchor),
+      presentedView.topAnchor.constraint(
+        greaterThanOrEqualTo: context.containerView.safeAreaLayoutGuide.topAnchor,
+        constant: 60
+      )
+    ]
+
+    dismissedConstraints = [
+      presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
+      presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
+      presentedView.topAnchor.constraint(equalTo: context.containerView.bottomAnchor)
+    ]
+
+    NSLayoutConstraint.activate(dismissedConstraints)
+
+    context.containerView.setNeedsLayout()
+    context.containerView.layoutIfNeeded()
+
+    NSLayoutConstraint.deactivate(dismissedConstraints)
+    NSLayoutConstraint.activate(presentedConstraints)
+
+    UIView.animate(
+      withDuration: transitionDuration(using: context),
+      delay: 0,
+      usingSpringWithDamping: 1,
+      initialSpringVelocity: 0,
+      options: .curveEaseInOut,
+      animations: {
+        darkOverlayView.alpha = 1.0
+        context.containerView.setNeedsLayout()
+        context.containerView.layoutIfNeeded()
+      },
+      completion: { _ in
+        context.completeTransition(true)
+      })
+  }
+
+  private func dismiss(using context: UIViewControllerContextTransitioning) {
+    NSLayoutConstraint.deactivate(presentedConstraints)
+    NSLayoutConstraint.activate(dismissedConstraints)
+
+    UIView.animate(
+      withDuration: transitionDuration(using: context),
+      delay: 0,
+      usingSpringWithDamping: 1,
+      initialSpringVelocity: 0,
+      options: .curveEaseInOut,
+      animations: { [weak darkOverlayView] in
+        darkOverlayView?.alpha = 0.0
+        context.containerView.setNeedsLayout()
+        context.containerView.layoutIfNeeded()
+      },
+      completion: { [weak self] _ in
+        context.completeTransition(true)
+        self?.onDismissal?()
+      }
+    )
+  }
+
+  @objc private func didTapOverlay() {
+    if let presentingController, isDismissableOnBackground {
+      presentingController.dismiss(animated: true)
+    }
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/BottomTransitioningDelegate.swift b/Sources/AppNavigation/CustomTransitions/BottomTransitioningDelegate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b30e549738b953c01702f1ca6897b6f50899fa9c
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/BottomTransitioningDelegate.swift
@@ -0,0 +1,25 @@
+import UIKit
+
+final class BottomTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
+  var isDismissableOnBackgroundTouch: Bool = true
+  private var transition: BottomTransition?
+
+  func animationController(
+    forPresented presented: UIViewController,
+    presenting: UIViewController,
+    source: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    transition = BottomTransition(isDismissableOnBackgroundTouch) { [weak self] in
+      guard let self else { return }
+      self.transition = nil
+    }
+    return transition
+  }
+
+  func animationController(
+    forDismissed dismissed: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    transition?.direction = .dismiss
+    return transition
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/LeftAnimator.swift b/Sources/AppNavigation/CustomTransitions/LeftAnimator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6944551740e8cd93364a9ddf06e2cc8adac38b0d
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/LeftAnimator.swift
@@ -0,0 +1,23 @@
+import UIKit
+
+protocol LeftAnimating {
+  func animate(in containerView: UIView, to progress: CGFloat)
+}
+
+struct LeftAnimator: LeftAnimating {
+  func animate(in containerView: UIView, to progress: CGFloat) {
+    guard let fromView = containerView.viewWithTag(LeftPresentTransition.fromViewTag) else { return }
+
+    let cornerRadius = progress * 24
+    let shadowOpacity = Float(progress)
+    let offsetX = containerView.bounds.size.width * 0.5 * progress
+    let offsetY = containerView.bounds.size.height * 0.08 * progress
+    let scale = 1 - (0.25 * progress)
+
+    fromView.subviews.first?.layer.cornerRadius = cornerRadius
+    fromView.layer.shadowOpacity = shadowOpacity
+    fromView.transform = CGAffineTransform.identity
+      .translatedBy(x: offsetX, y: offsetY)
+      .scaledBy(x: scale, y: scale)
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/LeftDismissInteractor.swift b/Sources/AppNavigation/CustomTransitions/LeftDismissInteractor.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c7d7f7868da64721df0ebb52249c7807813f64bb
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/LeftDismissInteractor.swift
@@ -0,0 +1,69 @@
+import UIKit
+
+protocol LeftDismissInteracting: UIViewControllerInteractiveTransitioning {
+  var interactionInProgress: Bool { get }
+  func setup(view: UIView, action: @escaping (() -> Void))
+}
+
+final class LeftDismissInteractor:
+  UIPercentDrivenInteractiveTransition, LeftDismissInteracting {
+  private var action: (() -> Void)?
+  public var interactionInProgress = false
+  private var shouldFinishTransition = false
+
+  func setup(view: UIView, action: @escaping (() -> Void)) {
+    view.addGestureRecognizer(UIPanGestureRecognizer(
+      target: self,
+      action: #selector(handlePanGesture(_:))
+    ))
+    view.addGestureRecognizer(UITapGestureRecognizer(
+      target: self,
+      action: #selector(handleTapGesture(_:))
+    ))
+    self.action = action
+  }
+
+  @objc
+  private func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
+    action?()
+  }
+
+  @objc
+  private func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
+    guard let view = recognizer.view,
+          let containerView = view.superview
+    else { return }
+
+    let viewWidth = containerView.bounds.size.width
+    guard viewWidth > 0 else { return }
+
+    let translation = recognizer.translation(in: view)
+    let progress = min(1, max(0, -translation.x / (viewWidth * 0.8)))
+
+    switch recognizer.state {
+    case .possible, .failed:
+      interactionInProgress = false
+      
+    case .began:
+      interactionInProgress = true
+      shouldFinishTransition = false
+      action?()
+
+    case .changed:
+      shouldFinishTransition = progress >= 0.5
+      update(progress)
+
+    case .cancelled:
+      interactionInProgress = false
+      cancel()
+
+    case .ended:
+      interactionInProgress = false
+      shouldFinishTransition ? finish() : cancel()
+
+    @unknown default:
+      interactionInProgress = false
+      cancel()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/LeftDismissTransition.swift b/Sources/AppNavigation/CustomTransitions/LeftDismissTransition.swift
new file mode 100644
index 0000000000000000000000000000000000000000..001ccf8ace53ab9fa411eb2a6014cfe6acaf36b9
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/LeftDismissTransition.swift
@@ -0,0 +1,34 @@
+import UIKit
+
+final class LeftDismissTransition: NSObject, UIViewControllerAnimatedTransitioning {
+  let menuAnimator: LeftAnimating
+  let viewAnimator: UIViewAnimating.Type
+
+  init(
+    menuAnimator: LeftAnimating,
+    viewAnimator: UIViewAnimating.Type
+  ) {
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  func transitionDuration(
+    using context: UIViewControllerContextTransitioning?
+  ) -> TimeInterval { 0.25 }
+
+  func animateTransition(
+    using context: UIViewControllerContextTransitioning
+  ) {
+    viewAnimator.animate(
+      withDuration: transitionDuration(using: context),
+      animations: {
+        self.menuAnimator.animate(in: context.containerView, to: 0)
+      },
+      completion: { _ in
+        let isCancelled = context.transitionWasCancelled
+        context.completeTransition(isCancelled == false)
+      }
+    )
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/LeftPresentTransition.swift b/Sources/AppNavigation/CustomTransitions/LeftPresentTransition.swift
new file mode 100644
index 0000000000000000000000000000000000000000..3af434fff9f4d7248e28c44ba56d00c93b2e6ad1
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/LeftPresentTransition.swift
@@ -0,0 +1,68 @@
+import UIKit
+
+final class LeftPresentTransition: NSObject, UIViewControllerAnimatedTransitioning {
+  let dismissInteractor: LeftDismissInteracting
+  let menuAnimator: LeftAnimating
+  let viewAnimator: UIViewAnimating.Type
+
+  static let fromViewTag = UUID().hashValue
+
+  init(
+    dismissInteractor: LeftDismissInteracting,
+    menuAnimator: LeftAnimating,
+    viewAnimator: UIViewAnimating.Type
+  ) {
+    self.dismissInteractor = dismissInteractor
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  func transitionDuration(
+    using context: UIViewControllerContextTransitioning?
+  ) -> TimeInterval { 0.25 }
+
+  func animateTransition(
+    using context: UIViewControllerContextTransitioning
+  ) {
+    guard let fromVC = context.viewController(forKey: .from),
+          let fromSnapshot = fromVC.view.snapshotView(afterScreenUpdates: true),
+          let toVC = context.viewController(forKey: .to)
+    else {
+      context.completeTransition(false)
+      return
+    }
+
+    context.containerView.addSubview(toVC.view)
+    toVC.view.frame = context.containerView.bounds
+
+    let fromView = UIView()
+    fromView.tag = Self.fromViewTag
+    context.containerView.addSubview(fromView)
+    fromView.frame = context.containerView.bounds
+    fromView.layer.shadowColor = UIColor.black.cgColor
+    fromView.layer.shadowOpacity = 1
+    fromView.layer.shadowOffset = .zero
+    fromView.layer.shadowRadius = 32
+    fromView.addSubview(fromSnapshot)
+    fromSnapshot.frame = fromView.bounds
+    fromSnapshot.layer.cornerRadius = 0
+    fromSnapshot.layer.masksToBounds = true
+
+    dismissInteractor.setup(
+      view: fromView,
+      action: { fromVC.dismiss(animated: true) }
+    )
+
+    viewAnimator.animate(
+      withDuration: transitionDuration(using: context),
+      animations: {
+        self.menuAnimator.animate(in: context.containerView, to: 1)
+      },
+      completion: { _ in
+        let isCancelled = context.transitionWasCancelled
+        context.completeTransition(isCancelled == false)
+      }
+    )
+  }
+}
diff --git a/Sources/AppNavigation/CustomTransitions/LeftTransitioningDelegate.swift b/Sources/AppNavigation/CustomTransitions/LeftTransitioningDelegate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7b918587e8b49a67227fd4d04a9a08aec095a979
--- /dev/null
+++ b/Sources/AppNavigation/CustomTransitions/LeftTransitioningDelegate.swift
@@ -0,0 +1,55 @@
+import UIKit
+
+protocol UIViewAnimating {
+  static func animate(
+    withDuration duration: TimeInterval,
+    animations: @escaping (() -> Void),
+    completion: ((Bool) -> Void)?
+  )
+}
+
+extension UIView: UIViewAnimating {}
+
+final class LeftTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
+  let menuAnimator: LeftAnimating
+  let viewAnimator: UIViewAnimating.Type
+  let dismissInteractor: LeftDismissInteracting
+
+  init(
+    dismissInteractor: LeftDismissInteracting = LeftDismissInteractor(),
+    menuAnimator: LeftAnimating = LeftAnimator(),
+    viewAnimator: UIViewAnimating.Type = UIView.self
+  ) {
+    self.dismissInteractor = dismissInteractor
+    self.menuAnimator = menuAnimator
+    self.viewAnimator = viewAnimator
+    super.init()
+  }
+
+  func animationController(
+    forPresented presented: UIViewController,
+    presenting: UIViewController,
+    source: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    LeftPresentTransition(
+      dismissInteractor: dismissInteractor,
+      menuAnimator: menuAnimator,
+      viewAnimator: viewAnimator
+    )
+  }
+
+  func animationController(
+    forDismissed dismissed: UIViewController
+  ) -> UIViewControllerAnimatedTransitioning? {
+    LeftDismissTransition(
+      menuAnimator: menuAnimator,
+      viewAnimator: viewAnimator
+    )
+  }
+
+  func interactionControllerForDismissal(
+    using animator: UIViewControllerAnimatedTransitioning
+  ) -> UIViewControllerInteractiveTransitioning? {
+    dismissInteractor.interactionInProgress ? dismissInteractor : nil
+  }
+}
diff --git a/Sources/AppNavigation/Dependency.swift b/Sources/AppNavigation/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c11e4ce52060f110c1a42a5436eed5a3bde96740
--- /dev/null
+++ b/Sources/AppNavigation/Dependency.swift
@@ -0,0 +1,26 @@
+import Dependencies
+import XCTestDynamicOverlay
+
+public enum NavigatorKey: TestDependencyKey {
+  public static let testValue: Navigator = UnimplementedNavigator()
+}
+
+public extension DependencyValues {
+  var navigator: Navigator {
+    get { self[NavigatorKey.self] }
+    set { self[NavigatorKey.self] = newValue }
+  }
+}
+
+public struct UnimplementedNavigator: Navigator {
+  public init() {}
+
+  public func perform(_ action: Action, completion: @escaping () -> Void) {
+    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.perform not implemented")
+  }
+
+  public func canPerform(_ action: Action) -> Bool {
+    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.canPerform not implemented")
+    return false
+  }
+}
diff --git a/Sources/AppNavigation/Generic/DismissModal.swift b/Sources/AppNavigation/Generic/DismissModal.swift
new file mode 100644
index 0000000000000000000000000000000000000000..5511e991db9441133e56b4336bfe71eb5a6e4591
--- /dev/null
+++ b/Sources/AppNavigation/Generic/DismissModal.swift
@@ -0,0 +1,33 @@
+import UIKit
+
+/// Dismiss view controller presented from provided view controller
+public struct DismissModal: Action {
+  /// - Parameters:
+  ///   - parent: Parent view controller from which dismiss happens
+  ///   - animated: Animate the transition
+  public init(
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Parent view controller from which dismiss happens
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `DismissModal` action
+public struct DismissModalNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: DismissModal, completion: @escaping () -> Void) {
+    action.parent.dismiss(
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/Generic/OpenLeft.swift b/Sources/AppNavigation/Generic/OpenLeft.swift
new file mode 100644
index 0000000000000000000000000000000000000000..90302e792da6cc98fa2456e800820b4d4e00088b
--- /dev/null
+++ b/Sources/AppNavigation/Generic/OpenLeft.swift
@@ -0,0 +1,45 @@
+import UIKit
+
+/// Open left view controller on provided parent view controller
+public struct OpenLeft: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to present
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    _ viewController: UIViewController,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.viewController = viewController
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// View controller to present
+  public var viewController: UIViewController
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `OpenLeft` action
+public struct OpenLeftNavigator: TypedNavigator {
+  let transitioningDelegate = LeftTransitioningDelegate()
+
+  public init() {}
+
+  public func perform(_ action: OpenLeft, completion: @escaping () -> Void) {
+    action.viewController.transitioningDelegate = transitioningDelegate
+    action.viewController.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      action.viewController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/Generic/OpenUp.swift b/Sources/AppNavigation/Generic/OpenUp.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dfcedc3fafa521134e3ca871e803538503b43f02
--- /dev/null
+++ b/Sources/AppNavigation/Generic/OpenUp.swift
@@ -0,0 +1,52 @@
+import UIKit
+
+/// Open up view controller on provided parent view controller
+public struct OpenUp: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to present
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  ///   - dismissable: Dismissable upon background touch flag
+  public init(
+    _ viewController: UIViewController,
+    from parent: UIViewController,
+    animated: Bool = true,
+    dismissable: Bool = true
+  ) {
+    self.viewController = viewController
+    self.parent = parent
+    self.animated = animated
+    self.dismissable = dismissable
+  }
+
+  /// View controller to present
+  public var viewController: UIViewController
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+
+  /// Dismissable upon background touch flag
+  public var dismissable: Bool
+}
+
+/// Performs `OpenUp` action
+public struct OpenUpNavigator: TypedNavigator {
+  let transitioningDelegate = BottomTransitioningDelegate()
+
+  public init() {}
+
+  public func perform(_ action: OpenUp, completion: @escaping () -> Void) {
+    transitioningDelegate.isDismissableOnBackgroundTouch = action.dismissable
+    action.viewController.transitioningDelegate = transitioningDelegate
+    action.viewController.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      action.viewController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/Generic/PopTo.swift b/Sources/AppNavigation/Generic/PopTo.swift
new file mode 100644
index 0000000000000000000000000000000000000000..15af276aa8f70d29b7a3266be72555c0bd69bbb9
--- /dev/null
+++ b/Sources/AppNavigation/Generic/PopTo.swift
@@ -0,0 +1,44 @@
+import UIKit
+
+/// Pop to the view controller on a given navigation controller
+public struct PopTo: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to which should pop
+  ///   - navigationController: Navigation controller on which pop should happen
+  ///   - animated: Animate the transition
+  public init(
+    _ viewController: UIViewController,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.viewController = viewController
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// View controller to which should pop
+  public var viewController: UIViewController
+
+  /// Navigation controller on which pop should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PopTo` action
+public struct PopToNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PopTo, completion: @escaping () -> Void) {
+    action.navigationController.popToViewController(
+      action.viewController,
+      animated: action.animated
+    )
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/Generic/PopToRoot.swift b/Sources/AppNavigation/Generic/PopToRoot.swift
new file mode 100644
index 0000000000000000000000000000000000000000..5918a3476f9ba0a23d6413173dc764e7df7a7052
--- /dev/null
+++ b/Sources/AppNavigation/Generic/PopToRoot.swift
@@ -0,0 +1,35 @@
+import UIKit
+
+/// Pops to root view controller on a given navigation controller
+public struct PopToRoot: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which pop should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which pop should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PopToRoot` action
+public struct PopToRootNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PopToRoot, completion: @escaping () -> Void) {
+    action.navigationController.popToRootViewController(animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/Generic/PresentModal.swift b/Sources/AppNavigation/Generic/PresentModal.swift
new file mode 100644
index 0000000000000000000000000000000000000000..23db172f067f1131a7e557f70c356c00c27d70cd
--- /dev/null
+++ b/Sources/AppNavigation/Generic/PresentModal.swift
@@ -0,0 +1,40 @@
+import UIKit
+
+/// Present view controller on provided parent view controller
+public struct PresentModal: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to present
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    _ viewController: UIViewController,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.viewController = viewController
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// View controller to present
+  public var viewController: UIViewController
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentModal` action
+public struct PresentModalNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PresentModal, completion: @escaping () -> Void) {
+    action.parent.present(
+      action.viewController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/Generic/Push.swift b/Sources/AppNavigation/Generic/Push.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a0a01ea670a9bfe255e128b30547eeb79dfbcca6
--- /dev/null
+++ b/Sources/AppNavigation/Generic/Push.swift
@@ -0,0 +1,41 @@
+import UIKit
+
+/// Push view controller on a given navigation controller
+public struct Push: Action {
+  /// - Parameters:
+  ///   - viewController: View controller to which should be pushed
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    _ viewController: UIViewController,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.viewController = viewController
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// View controller to which should be pushed
+  public var viewController: UIViewController
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `Push` action
+public struct PushNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: Push, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(action.viewController, animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/Generic/SetStack.swift b/Sources/AppNavigation/Generic/SetStack.swift
new file mode 100644
index 0000000000000000000000000000000000000000..23ca3a679bf6ddbdb6869aff208a776172161594
--- /dev/null
+++ b/Sources/AppNavigation/Generic/SetStack.swift
@@ -0,0 +1,44 @@
+import UIKit
+
+/// Sets view controllers on a given navigation controller
+public struct SetStack: Action {
+  /// - Parameters:
+  ///   - viewControllers: View controllers that should be set
+  ///   - navigationController: Navigation controller on which view controllers should be set
+  ///   - animated: Animate the transition
+  public init(
+    _ viewControllers: [UIViewController],
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.viewControllers = viewControllers
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// View controllers that should be set
+  public var viewControllers: [UIViewController]
+
+  /// Navigation controller on which view controllers should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `SetStack` action
+public struct SetStackNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: SetStack, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers(
+      action.viewControllers,
+      animated: action.animated
+    )
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/Navigator.swift b/Sources/AppNavigation/Navigator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c37ca8d190ffd9f19fb667dcf37fd1718a9f9e64
--- /dev/null
+++ b/Sources/AppNavigation/Navigator.swift
@@ -0,0 +1,23 @@
+/// Navigator that performs a navigation action
+public protocol Navigator {
+  /// Returns true if the navigator can perform the action
+  /// - Default implementation returns true for any action
+  /// - Parameter action: navigation action
+  func canPerform(_ action: Action) -> Bool
+
+  /// Performs the navigation action
+  /// - Parameters:
+  ///   - action: navigation action
+  ///   - completion: closure that will be executed after performing the action
+  func perform(_ action: Action, completion: @escaping () -> Void)
+}
+
+public extension Navigator {
+  func canPerform(_ action: Action) -> Bool { true }
+
+  /// Performs the navigation action with empty completion closure
+  /// - Parameter action: navigation action
+  func perform(_ action: Action) {
+    perform(action, completion: {})
+  }
+}
diff --git a/Sources/AppNavigation/PresentActivitySheet.swift b/Sources/AppNavigation/PresentActivitySheet.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1ba69910f41607fc78fd86d99f75ee46f02a6de7
--- /dev/null
+++ b/Sources/AppNavigation/PresentActivitySheet.swift
@@ -0,0 +1,43 @@
+import UIKit
+
+/// Presents `UIActivityViewController` on a given parent view controller
+public struct PresentActivitySheet: Action {
+  /// - Parameters:
+  ///   - items: Items to be displayed at the activity sheet controller
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    items: [Any],
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.items = items
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Items to be displayed at the activity sheet controller
+  public var items: [Any]
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentActivitySheet` action
+public struct PresentActivitySheetNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PresentActivitySheet, completion: @escaping () -> Void) {
+    action.parent.present(
+      UIActivityViewController(
+        activityItems: action.items,
+        applicationActivities: nil
+      ),
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentCamera.swift b/Sources/AppNavigation/PresentCamera.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f5fa18ef1f7f2446a637e0a35fadc906590b3534
--- /dev/null
+++ b/Sources/AppNavigation/PresentCamera.swift
@@ -0,0 +1,37 @@
+import UIKit
+
+/// Presents `Camera` on provided parent view controller
+public struct PresentCamera: Action {
+  /// - Parameters:
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentCamera` action
+public struct PresentCameraNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PresentCamera, completion: @escaping () -> Void) {
+    let imagePickerController = UIImagePickerController()
+    imagePickerController.sourceType = .camera
+    imagePickerController.delegate = action.parent as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
+    action.parent.present(
+      imagePickerController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentChat.swift b/Sources/AppNavigation/PresentChat.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ef6ab52f5e7d00be89a1d0b5b329aa7496727e7a
--- /dev/null
+++ b/Sources/AppNavigation/PresentChat.swift
@@ -0,0 +1,49 @@
+import UIKit
+import XXModels
+
+/// Pushes `Chat` on a given navigation controller
+public struct PresentChat: Action {
+  /// - Parameters:
+  ///   - contact: Model to build the view controller which will be pushed
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    contact: Contact,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.contact = contact
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Model to build the view controller which will be pushed
+  public var contact: Contact
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentChat` action
+public struct PresentChatNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (Contact) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (Contact) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentChat, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(action.contact), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentChatList.swift b/Sources/AppNavigation/PresentChatList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1cdca2246f9a9de7e3796caa57cef56f67c65270
--- /dev/null
+++ b/Sources/AppNavigation/PresentChatList.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `ChatList` on a given navigation controller stack
+public struct PresentChatList: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentChatList` action
+public struct PresentChatListNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentChatList, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentContact.swift b/Sources/AppNavigation/PresentContact.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dd1fca4beb590248d1baff41b5c70e1c735182bc
--- /dev/null
+++ b/Sources/AppNavigation/PresentContact.swift
@@ -0,0 +1,49 @@
+import UIKit
+import XXModels
+
+/// Pushes `Contact` on a given navigation controller
+public struct PresentContact: Action {
+  /// - Parameters:
+  ///   - contact: Model to build the view controller which will be pushed
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    contact: Contact,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.contact = contact
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Model to build the view controller which will be pushed
+  public var contact: Contact
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentContact` action
+public struct PresentContactNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (Contact) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (Contact) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentContact, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(action.contact), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentContactList.swift b/Sources/AppNavigation/PresentContactList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..bdf9d30fc3a9118ced62cb0ae8e6c44322f48f0e
--- /dev/null
+++ b/Sources/AppNavigation/PresentContactList.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `ContactList` on a given navigation controller stack
+public struct PresentContactList: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentContactList` action
+public struct PresentContactListNavigator: TypedNavigator {
+  /// View controller to which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentContactList, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentCountryList.swift b/Sources/AppNavigation/PresentCountryList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..5365cf6b1e2c925fdf8fee7dd7a34b17efe0c499
--- /dev/null
+++ b/Sources/AppNavigation/PresentCountryList.swift
@@ -0,0 +1,47 @@
+import UIKit
+
+/// Presents `CountryList` on a given parent view controller
+public struct PresentCountryList: Action {
+  /// - Parameters:
+  ///   - completion: Completion closure with the selected country model
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    completion: @escaping (Any) -> Void,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.completion = completion
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Completion closure with the selected country model
+  public var completion: (Any) -> Void
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentCountryList` action
+public struct PresentCountryListNavigator: TypedNavigator {
+  /// View controller which should be presented
+  var viewController: (@escaping (Any) -> Void) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: view controller which should be presented
+  public init(_ viewController: @escaping (@escaping (Any) -> Void) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentCountryList, completion: @escaping () -> Void) {
+    action.parent.present(
+      viewController(action.completion),
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentCreateGroupDrawer.swift b/Sources/AppNavigation/PresentCreateGroupDrawer.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8abf07fdaa88842ef7d9ef9bdc8b657d375dc872
--- /dev/null
+++ b/Sources/AppNavigation/PresentCreateGroupDrawer.swift
@@ -0,0 +1,56 @@
+import UIKit
+import XXModels
+
+/// Opens up `CreateGroup` on a given parent view controller
+public struct PresentCreateGroup: Action {
+  /// - Parameters:
+  ///   - members: Collection of contacts that will be in the group
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    members: [Contact],
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.members = members
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Collection of contacts that will be in the group
+  public var members: [Contact]
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentCreateGroup` action
+public struct PresentCreateGroupNavigator: TypedNavigator {
+  /// Custom transitioning delegate
+  let transitioningDelegate = BottomTransitioningDelegate()
+
+  /// View controller which should be opened up
+  var viewController: ([Contact]) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: view controller which should be presented
+  public init(_ viewController: @escaping ([Contact]) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentCreateGroup, completion: @escaping () -> Void) {
+    transitioningDelegate.isDismissableOnBackgroundTouch = true
+    let controller = viewController(action.members)
+    controller.transitioningDelegate = transitioningDelegate
+    controller.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      controller,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentDrawer.swift b/Sources/AppNavigation/PresentDrawer.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8e49f814efafa6552f2c3f2b8c37ef79a83bef8f
--- /dev/null
+++ b/Sources/AppNavigation/PresentDrawer.swift
@@ -0,0 +1,61 @@
+import UIKit
+
+/// Opens up `Drawer` on a given parent view controller
+public struct PresentDrawer: Action {
+  /// - Parameters:
+  ///   - items: Collection of drawer items that will be present on the view controller
+  ///   - isDismissable: Flag that differentiates whether this presentation is dismissable on background touch
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    items: [Any],
+    isDismissable: Bool,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.items = items
+    self.isDismissable = isDismissable
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Collection of drawer items that will be present on the view controller
+  public var items: [Any]
+
+  /// Flag that differentiates whether this presentation is dismissable on background touch
+  public var isDismissable: Bool
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentDrawer` action
+public struct PresentDrawerNavigator: TypedNavigator {
+  /// Custom transitioning delegate
+  let transitioningDelegate = BottomTransitioningDelegate()
+
+  /// View controller which should be opened up
+  var viewController: ([Any]) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: view controller which should be presented
+  public init(_ viewController: @escaping ([Any]) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentDrawer, completion: @escaping () -> Void) {
+    transitioningDelegate.isDismissableOnBackgroundTouch = action.isDismissable
+    let controller = viewController(action.items)
+    controller.transitioningDelegate = transitioningDelegate
+    controller.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      controller,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentGroupChat.swift b/Sources/AppNavigation/PresentGroupChat.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e5695a778eca7820292b449d0209d697fa006162
--- /dev/null
+++ b/Sources/AppNavigation/PresentGroupChat.swift
@@ -0,0 +1,49 @@
+import UIKit
+import XXModels
+
+/// Pushes `GroupChat` on a given navigation controller
+public struct PresentGroupChat: Action {
+  /// - Parameters:
+  ///   - groupInfo: Model to build the view controller which will be pushed
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    groupInfo: GroupInfo,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.groupInfo = groupInfo
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Model to build the view controller which will be pushed
+  public var groupInfo: GroupInfo
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentGroupChat` action
+public struct PresentGroupChatNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (GroupInfo) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (GroupInfo) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentGroupChat, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(action.groupInfo), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentGroupDraft.swift b/Sources/AppNavigation/PresentGroupDraft.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9190507f7e89baf10c89357c3245162d6f1126fe
--- /dev/null
+++ b/Sources/AppNavigation/PresentGroupDraft.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `GroupDraft` on a given navigation controller
+public struct PresentGroupDraft: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentGroupDraft` action
+public struct PresentGroupDraftNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentGroupDraft, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentMemberList.swift b/Sources/AppNavigation/PresentMemberList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..3fa6582f85d7e92b9d476248454c3dda3629efc8
--- /dev/null
+++ b/Sources/AppNavigation/PresentMemberList.swift
@@ -0,0 +1,14 @@
+import XXModels
+
+public struct PresentMemberList: Action {
+  public var members: [Contact]
+  public var animated: Bool
+
+  public init(
+    members: [Contact],
+    animated: Bool = true
+  ) {
+    self.members = members
+    self.animated = animated
+  }
+}
diff --git a/Sources/AppNavigation/PresentMenu.swift b/Sources/AppNavigation/PresentMenu.swift
new file mode 100644
index 0000000000000000000000000000000000000000..59561cc1acf0f0f5121f26d89f1b5b14a22a4cd1
--- /dev/null
+++ b/Sources/AppNavigation/PresentMenu.swift
@@ -0,0 +1,66 @@
+import UIKit
+
+/// Options that can be lead to a flow on the menu UI
+public enum MenuItem {
+  case join
+  case scan
+  case chats
+  case share
+  case profile
+  case contacts
+  case requests
+  case settings
+  case dashboard
+}
+
+/// Opens left `Menu` on a given parent view controller
+public struct PresentMenu: Action {
+  /// - Parameters:
+  ///   - currentItem: A correlation with the flow that this controller is being presented
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    currentItem: MenuItem,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.currentItem = currentItem
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// A correlation with the flow that this controller is being presented
+  public var currentItem: MenuItem
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentMenu` action
+public struct PresentMenuNavigator: TypedNavigator {
+  /// Custom transitioning delegate
+  let transitioningDelegate = LeftTransitioningDelegate()
+
+  /// View controller which should be opened left
+  var viewController: (MenuItem, UINavigationController?) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: view controller which should be presented
+  public init(_ viewController: @escaping (MenuItem, UINavigationController?) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentMenu, completion: @escaping () -> Void) {
+    let controller = viewController(action.currentItem, action.parent.navigationController)
+    controller.transitioningDelegate = transitioningDelegate
+    controller.modalPresentationStyle = .overFullScreen
+    action.parent.present(
+      controller,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentNickname.swift b/Sources/AppNavigation/PresentNickname.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8c6bd57c346a9beed71e8b40595e2b7367590600
--- /dev/null
+++ b/Sources/AppNavigation/PresentNickname.swift
@@ -0,0 +1,60 @@
+import UIKit
+
+/// Opens up `Nickname` on a given parent view controller
+public struct PresentNickname: Action {
+  /// - Parameters:
+  ///   - prefilled: Optional value to be set as placeholder/pre-existent text
+  ///   - completion: Closure that passes the value of the text set
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    prefilled: String?,
+    completion: @escaping (String) -> Void,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.prefilled = prefilled
+    self.completion = completion
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Optional value to be set as placeholder/pre-existent text
+  public var prefilled: String?
+
+  /// Closure that passes the value of the text set
+  public var completion: (String) -> Void
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentNickname` action
+public struct PresentNicknameNavigator: TypedNavigator {
+  /// Custom transitioning delegate
+  let transitioningDelegate = BottomTransitioningDelegate()
+
+  /// View controller which should be opened up
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: view controller which should be presented
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentNickname, completion: @escaping () -> Void) {
+    let controller = viewController()
+    controller.transitioningDelegate = transitioningDelegate
+    controller.modalPresentationStyle = .overFullScreen
+
+    action.parent.present(
+      controller,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingCode.swift b/Sources/AppNavigation/PresentOnboardingCode.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7ed2f50c8dd725db9673ff22e71762cbef3d8ecf
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingCode.swift
@@ -0,0 +1,61 @@
+import UIKit
+
+/// Pushes `OnboardingCode` on a given navigation controller
+public struct PresentOnboardingCode: Action {
+  /// - Parameters:
+  ///   - isEmail: Flag to differentiate email or phone code
+  ///   - content: Content that is being set if confirmation code gets validated
+  ///   - confirmationId: Confirmation id to validate with third-party
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Flag to differentiate email or phone code
+  public var isEmail: Bool
+
+  /// Content that is being set if confirmation code gets validated
+  public var content: String
+
+  /// Confirmation id to validate with third-party
+  public var confirmationId: String
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingCode` action
+public struct PresentOnboardingCodeNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (Bool, String, String) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (Bool, String, String) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingCode, completion: @escaping () -> Void) {
+    let controller = viewController(action.isEmail, action.content, action.confirmationId)
+    action.navigationController.pushViewController(controller, animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingEmail.swift b/Sources/AppNavigation/PresentOnboardingEmail.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4f57119e0157d8b480cc55c41fea90bde38eac2e
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingEmail.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `OnboardingEmail` on a given navigation controller stack
+public struct PresentOnboardingEmail: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingEmail` action
+public struct PresentOnboardingEmailNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingEmail, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingPhone.swift b/Sources/AppNavigation/PresentOnboardingPhone.swift
new file mode 100644
index 0000000000000000000000000000000000000000..eca7c89605f99e1f6ec8e982150907f7f7ef80d0
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingPhone.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `OnboardingPhone` on a given navigation controller stack
+public struct PresentOnboardingPhone: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingPhone` action
+public struct PresentOnboardingPhoneNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingPhone, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingStart.swift b/Sources/AppNavigation/PresentOnboardingStart.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e531c6909ea2e1087dfea80e608dcd384c7dafef
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingStart.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `OnboardingStart` on a given navigation controller stack
+public struct PresentOnboardingStart: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingStart` action
+public struct PresentOnboardingStartNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingStart, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingUsername.swift b/Sources/AppNavigation/PresentOnboardingUsername.swift
new file mode 100644
index 0000000000000000000000000000000000000000..428dc24a0b84c014e3473e575d7f2058ff92180e
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingUsername.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `OnboardingUsername` on a given navigation controller
+public struct PresentOnboardingUsername: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingUsername` action
+public struct PresentOnboardingUsernameNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingUsername, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentOnboardingWelcome.swift b/Sources/AppNavigation/PresentOnboardingWelcome.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0df955e7e77208e5dcc675220621b7f800403f82
--- /dev/null
+++ b/Sources/AppNavigation/PresentOnboardingWelcome.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `OnboardingWelcome` on a given navigation controller stack
+public struct PresentOnboardingWelcome: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentOnboardingWelcome` action
+public struct PresentOnboardingWelcomeNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentOnboardingWelcome, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentPassphrase.swift b/Sources/AppNavigation/PresentPassphrase.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6e208f26b048d5649c4badf2cafd5a3d43fd9d0e
--- /dev/null
+++ b/Sources/AppNavigation/PresentPassphrase.swift
@@ -0,0 +1,15 @@
+public struct PresentPassphrase: Action {
+  public var onCancel: () -> Void
+  public var onPasspharse: (String) -> Void
+  public var animated: Bool
+
+  public init(
+    onCancel: @escaping () -> Void,
+    onPassphrase: @escaping (String) -> Void,
+    animated: Bool = true
+  ) {
+    self.onCancel = onCancel
+    self.onPasspharse = onPassphrase
+    self.animated = animated
+  }
+}
diff --git a/Sources/AppNavigation/PresentPermissionRequest.swift b/Sources/AppNavigation/PresentPermissionRequest.swift
new file mode 100644
index 0000000000000000000000000000000000000000..76c89f1c94a814061473dfcb003466dc9795cddb
--- /dev/null
+++ b/Sources/AppNavigation/PresentPermissionRequest.swift
@@ -0,0 +1,59 @@
+import UIKit
+
+/// Types of permissions that can be requested to the user
+public enum PermissionType {
+  /// Device camera permission type
+  case camera
+
+  /// Camera roll and library permission type
+  case library
+
+  /// Device microphone permission type
+  case microphone
+}
+
+/// Presents `PermissionRequest` on provided parent view controller
+public struct PresentPermissionRequest: Action {
+  /// - Parameters:
+  ///   - type: Type of permission that is being requested
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    type: PermissionType,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.type = type
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Type of permission that is being requested
+  public var type: PermissionType
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentPermissionRequest` action
+public struct PresentPermissionRequestNavigator: TypedNavigator {
+  /// View controller which should be presented
+  var viewController: (PermissionType) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be presented
+  public init(_ viewController: @escaping (PermissionType) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentPermissionRequest, completion: @escaping () -> Void) {
+    action.parent.present(
+      viewController(action.type),
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentPhotoLibrary.swift b/Sources/AppNavigation/PresentPhotoLibrary.swift
new file mode 100644
index 0000000000000000000000000000000000000000..886b3c8b3c5bcf4468f02113d20865e3f2387d4d
--- /dev/null
+++ b/Sources/AppNavigation/PresentPhotoLibrary.swift
@@ -0,0 +1,36 @@
+import UIKit
+
+/// Presents `PhotoLibrary` on provided parent view controller
+public struct PresentPhotoLibrary: Action {
+  /// - Parameters:
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentPhotoLibrary` action
+public struct PresentPhotoLibraryNavigator: TypedNavigator {
+  public init() {}
+
+  public func perform(_ action: PresentPhotoLibrary, completion: @escaping () -> Void) {
+    let imagePickerController = UIImagePickerController()
+    imagePickerController.delegate = action.parent as? UIImagePickerControllerDelegate & UINavigationControllerDelegate
+    action.parent.present(
+      imagePickerController,
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/PresentProfile.swift b/Sources/AppNavigation/PresentProfile.swift
new file mode 100644
index 0000000000000000000000000000000000000000..42363e49108b8bb363987fd17c998240e8fc9554
--- /dev/null
+++ b/Sources/AppNavigation/PresentProfile.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `Profile` on a given navigation controller stack
+public struct PresentProfile: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentProfile` action
+public struct PresentProfileNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentProfile, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentProfileCode.swift b/Sources/AppNavigation/PresentProfileCode.swift
new file mode 100644
index 0000000000000000000000000000000000000000..db50a72d8f3ef9a5e40e6188025a68d44b924d5b
--- /dev/null
+++ b/Sources/AppNavigation/PresentProfileCode.swift
@@ -0,0 +1,61 @@
+import UIKit
+
+/// Pushes `ProfileCode` on a given navigation controller
+public struct PresentProfileCode: Action {
+  /// - Parameters:
+  ///   - isEmail: Flag to differentiate email or phone code
+  ///   - content: Content that is being set if confirmation code gets validated
+  ///   - confirmationId: Confirmation id to validate with third-party
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    isEmail: Bool,
+    content: String,
+    confirmationId: String,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.isEmail = isEmail
+    self.content = content
+    self.confirmationId = confirmationId
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Flag to differentiate email or phone code
+  public var isEmail: Bool
+
+  /// Content that is being set if confirmation code gets validated
+  public var content: String
+
+  /// Confirmation id to validate with third-party
+  public var confirmationId: String
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentProfileCode` action
+public struct PresentProfileCodeNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (Bool, String, String) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (Bool, String, String) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentProfileCode, completion: @escaping () -> Void) {
+    let controller = viewController(action.isEmail, action.content, action.confirmationId)
+    action.navigationController.pushViewController(controller, animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentProfileEmail.swift b/Sources/AppNavigation/PresentProfileEmail.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0ea2c524781d1046b806c65edd9be0931d0f7bc7
--- /dev/null
+++ b/Sources/AppNavigation/PresentProfileEmail.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `ProfileEmail` on a given navigation controller
+public struct PresentProfileEmail: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentProfileEmail` action
+public struct PresentProfileEmailNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentProfileEmail, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentProfilePhone.swift b/Sources/AppNavigation/PresentProfilePhone.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c669afe41c355ee6ef39fa1c38dbea2dae2a7583
--- /dev/null
+++ b/Sources/AppNavigation/PresentProfilePhone.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `ProfilePhone` on a given navigation controller
+public struct PresentProfilePhone: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentProfilePhone` action
+public struct PresentProfilePhoneNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentProfilePhone, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentRequests.swift b/Sources/AppNavigation/PresentRequests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..aa346ff45292234cc1576135d517b49625f04916
--- /dev/null
+++ b/Sources/AppNavigation/PresentRequests.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `Requests` on a given navigation controller stack
+public struct PresentRequests: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentRequests` action
+public struct PresentRequestsNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentRequests, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentRestoreList.swift b/Sources/AppNavigation/PresentRestoreList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..977c224537b219dff54e4ed87f87115c01af945d
--- /dev/null
+++ b/Sources/AppNavigation/PresentRestoreList.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `RestoreList` on a given navigation controller
+public struct PresentRestoreList: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentRestoreList` action
+public struct PresentRestoreListNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentRestoreList, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSFTP.swift b/Sources/AppNavigation/PresentSFTP.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dee1bde64055af2fb2fa7fa4e8006bed8270c20b
--- /dev/null
+++ b/Sources/AppNavigation/PresentSFTP.swift
@@ -0,0 +1,49 @@
+import UIKit
+
+/// Pushes `SFTP` on a given navigation controller
+public struct PresentSFTP: Action {
+  /// - Parameters:
+  ///   - completion: Completion closure with host, username and password
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    completion: @escaping (String, String, String) -> Void,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.completion = completion
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Completion closure with host, username and password
+  public var completion: (String, String, String) -> Void
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSFTP` action
+public struct PresentSFTPNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: (@escaping (String, String, String) -> Void) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping (@escaping (String, String, String) -> Void) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSFTP, completion: @escaping () -> Void) {
+    let controller = viewController(action.completion)
+    action.navigationController.pushViewController(controller, animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentScan.swift b/Sources/AppNavigation/PresentScan.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d4fb08cb2be013598154342439480972f26f4e23
--- /dev/null
+++ b/Sources/AppNavigation/PresentScan.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `Scan` on a given navigation controller stack
+public struct PresentScan: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentScan` action
+public struct PresentScanNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentScan, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSearch.swift b/Sources/AppNavigation/PresentSearch.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4dc89878f03d712d3ccf5486a4be4c3dcab82673
--- /dev/null
+++ b/Sources/AppNavigation/PresentSearch.swift
@@ -0,0 +1,59 @@
+import UIKit
+
+/// Sets or Pushes `Search` on a given navigation controller
+public struct PresentSearch: Action {
+  /// - Parameters:
+  ///   - searching: Optional string to be searched upon further viewModel intialization
+  ///   - replacing: Flag to differentiate if should be a push or a set stack
+  ///   - navigationController: Navigation controller on which will be pushed or stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    searching: String?,
+    replacing: Bool,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.searching = searching
+    self.replacing = replacing
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Optional string to be searched upon further viewModel intialization
+  public var searching: String?
+
+  /// Flag to differentiate if should be a push or a set stack
+  public var replacing: Bool
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSearch` action
+public struct PresentSearchNavigator: TypedNavigator {
+  /// View controller which should be pushed or set in navigation stack
+  var viewController: (String?) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed or set in navigation stack
+  public init(_ viewController: @escaping (String?) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSearch, completion: @escaping () -> Void) {
+    if action.replacing {
+      action.navigationController.setViewControllers([viewController(action.searching)], animated: action.animated)
+    } else {
+      action.navigationController.pushViewController(viewController(action.searching), animated: action.animated)
+    }
+
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSettings.swift b/Sources/AppNavigation/PresentSettings.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e6a4871612234c122da83bdd6be5869b895062e8
--- /dev/null
+++ b/Sources/AppNavigation/PresentSettings.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Sets `Settings` on a given navigation controller stack
+public struct PresentSettings: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSettings` action
+public struct PresentSettingsNavigator: TypedNavigator {
+  /// View controller which should be set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSettings, completion: @escaping () -> Void) {
+    action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSettingsAccountDelete.swift b/Sources/AppNavigation/PresentSettingsAccountDelete.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e5691b4cda89a52c223c2c463fd96743465b1cd4
--- /dev/null
+++ b/Sources/AppNavigation/PresentSettingsAccountDelete.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `SettingsAccountDelete` on a given navigation controller
+public struct PresentSettingsAccountDelete: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSettingsAccountDelete` action
+public struct PresentSettingsAccountDeleteNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSettingsAccountDelete, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSettingsAdvanced.swift b/Sources/AppNavigation/PresentSettingsAdvanced.swift
new file mode 100644
index 0000000000000000000000000000000000000000..737f02fa2f6d97a8da754f821d1860502dcfa957
--- /dev/null
+++ b/Sources/AppNavigation/PresentSettingsAdvanced.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `SettingsAdvanced` on a given navigation controller
+public struct PresentSettingsAdvanced: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSettingsAdvanced` action
+public struct PresentSettingsAdvancedNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSettingsAdvanced, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentSettingsBackup.swift b/Sources/AppNavigation/PresentSettingsBackup.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f1d2ec5e3808f5bc45e8a968a03f8a4c0272f89a
--- /dev/null
+++ b/Sources/AppNavigation/PresentSettingsBackup.swift
@@ -0,0 +1,42 @@
+import UIKit
+
+/// Pushes `SettingsBackup` on a given navigation controller
+public struct PresentSettingsBackup: Action {
+  /// - Parameters:
+  ///   - navigationController: Navigation controller on which push should happen
+  ///   - animated: Animate the transition
+  public init(
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Navigation controller on which push should happen
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentSettingsBackup` action
+public struct PresentSettingsBackupNavigator: TypedNavigator {
+  /// View controller which should be pushed
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentSettingsBackup, completion: @escaping () -> Void) {
+    action.navigationController.pushViewController(viewController(), animated: action.animated)
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentTermsAndConditions.swift b/Sources/AppNavigation/PresentTermsAndConditions.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8baa2e06fb19f87e770eb5792b898f97e94bee65
--- /dev/null
+++ b/Sources/AppNavigation/PresentTermsAndConditions.swift
@@ -0,0 +1,53 @@
+import UIKit
+
+/// Sets or Pushes `TermsAndConditions` on a given navigation controller
+public struct PresentTermsAndConditions: Action {
+  /// - Parameters:
+  ///   - replacing: Flag to differentiate if should be a push or a set stack
+  ///   - navigationController: Navigation controller on which will be pushed or stack should be set
+  ///   - animated: Animate the transition
+  public init(
+    replacing: Bool,
+    on navigationController: UINavigationController,
+    animated: Bool = true
+  ) {
+    self.replacing = replacing
+    self.navigationController = navigationController
+    self.animated = animated
+  }
+
+  /// Flag to differentiate if should be a push or a set stack
+  public var replacing: Bool
+
+  /// Navigation controller on which stack should be set
+  public var navigationController: UINavigationController
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentTermsAndConditions` action
+public struct PresentTermsAndConditionsNavigator: TypedNavigator {
+  /// View controller which should be pushed or set in navigation stack
+  var viewController: () -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be pushed or set in navigation stack
+  public init(_ viewController: @escaping () -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentTermsAndConditions, completion: @escaping () -> Void) {
+    if action.replacing {
+      action.navigationController.setViewControllers([viewController()], animated: action.animated)
+    } else {
+      action.navigationController.pushViewController(viewController(), animated: action.animated)
+    }
+
+    if action.animated, let coordinator = action.navigationController.transitionCoordinator {
+      coordinator.animate(alongsideTransition: nil, completion: { _ in completion() })
+    } else {
+      completion()
+    }
+  }
+}
diff --git a/Sources/AppNavigation/PresentWebsite.swift b/Sources/AppNavigation/PresentWebsite.swift
new file mode 100644
index 0000000000000000000000000000000000000000..02abd2eef9dfb3709e1704d66c662b93524d6471
--- /dev/null
+++ b/Sources/AppNavigation/PresentWebsite.swift
@@ -0,0 +1,48 @@
+import UIKit
+import WebKit
+
+/// Presents `Website` on a given parent view controller
+public struct PresentWebsite: Action {
+  /// - Parameters:
+  ///   - urlString: Url that will be loaded on the web view
+  ///   - parent: Parent view controller from which presentation should happen
+  ///   - animated: Animate the transition
+  public init(
+    urlString: String,
+    from parent: UIViewController,
+    animated: Bool = true
+  ) {
+    self.urlString = urlString
+    self.parent = parent
+    self.animated = animated
+  }
+
+  /// Parent view controller from which presentation should happen
+  public var parent: UIViewController
+
+  /// Url that will be loaded on the web view
+  public var urlString: String
+
+  /// Animate the transition
+  public var animated: Bool
+}
+
+/// Performs `PresentWebsite` action
+public struct PresentWebsiteNavigator: TypedNavigator {
+  /// View controller which should be presented
+  var viewController: (String) -> UIViewController
+
+  /// - Parameters:
+  ///   - viewController: View controller which should be presented
+  public init(_ viewController: @escaping (String) -> UIViewController) {
+    self.viewController = viewController
+  }
+
+  public func perform(_ action: PresentWebsite, completion: @escaping () -> Void) {
+    action.parent.present(
+      viewController(action.urlString),
+      animated: action.animated,
+      completion: completion
+    )
+  }
+}
diff --git a/Sources/AppNavigation/TypedNavigator.swift b/Sources/AppNavigation/TypedNavigator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c351c98a2257a610fd7bbd291dcdab614597ee0d
--- /dev/null
+++ b/Sources/AppNavigation/TypedNavigator.swift
@@ -0,0 +1,46 @@
+/// Navigation that can perform action of a concrete type
+public protocol TypedNavigator: Navigator {
+  /// Type of the action that the navigator can perform
+  associatedtype ActionType: Action
+
+  /// Returns true if the action can be performed by the navigator
+  /// - Default implementation returns true for any action
+  /// - Parameter action: navigation action
+  func canPerform(_ action: ActionType) -> Bool
+
+  /// Performs the navigation action
+  /// - Parameters:
+  ///   - action: navigation action
+  ///   - completion: closure that will be executed after performing the action
+  func perform(_ action: ActionType, completion: @escaping () -> Void)
+}
+
+public extension TypedNavigator {
+  /// Returns true if the navigation action is of the type handled by the navigator
+  /// - Parameter action: navigation action
+  /// - Returns: true if action can be performed
+  func canPerform(_ action: Action) -> Bool {
+    if let action = action as? ActionType {
+      return canPerform(action)
+    }
+    return false
+  }
+
+  func canPerform(_ action: ActionType) -> Bool { true }
+
+  /// Performs the navigation action with empty completion closure
+  /// - Parameter action: navigation action
+  func perform(_ action: ActionType) {
+    perform(action, completion: {})
+  }
+
+  /// Performs the navigation action if its type matches `ActionType` handled by the navigator
+  /// - Parameters:
+  ///   - action: navigation action
+  ///   - completion: closure that will be executed after performing the action
+  func perform(_ action: Action, completion: @escaping () -> Void) {
+    if let action = action as? ActionType {
+      perform(action, completion: completion)
+    }
+  }
+}
diff --git a/Sources/Shared/swiftgen.yml b/Sources/AppResources/swiftgen.yml
similarity index 77%
rename from Sources/Shared/swiftgen.yml
rename to Sources/AppResources/swiftgen.yml
index 1811db25daa24e73f82a0022cc191d14e15f664b..3e4548e0eb8a79eefb0bb9f37d8d3ef7cc9338da 100644
--- a/Sources/Shared/swiftgen.yml
+++ b/Sources/AppResources/swiftgen.yml
@@ -2,7 +2,7 @@ strings:
   inputs: Resources/en.lproj
   outputs:
       templateName: structured-swift5
-      output: AutoGenerated/Strings.swift
+      output: Strings.swift
       params:
         enumName: Localized
         publicAccess: true
@@ -11,7 +11,7 @@ xcassets:
   inputs: Resources/Assets.xcassets
   outputs:
     templateName: swift5
-    output: AutoGenerated/Assets.swift
+    output: Assets.swift
     params:
       publicAccess: true
 
@@ -19,7 +19,7 @@ fonts:
   inputs: Resources/Fonts
   outputs:
     templateName: swift5
-    output: AutoGenerated/Fonts.swift
+    output: Fonts.swift
     params:
       enumName: Fonts
       publicAccess: true
diff --git a/Sources/BackupFeature/Controllers/BackupConfigController.swift b/Sources/BackupFeature/Controllers/BackupConfigController.swift
index 25772de76f0a5a0bc13a45ddc2789088b3307982..f2e0220380a545b5d8a79cc5c7517d7676930ba1 100644
--- a/Sources/BackupFeature/Controllers/BackupConfigController.swift
+++ b/Sources/BackupFeature/Controllers/BackupConfigController.swift
@@ -1,14 +1,14 @@
-import DI
 import UIKit
 import Shared
 import Combine
 import CloudFiles
-import Navigation
-import DrawerFeature
 import AppResources
+import AppNavigation
+import DrawerFeature
+import ComposableArchitecture
 
 final class BackupConfigController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = BackupConfigView()
 
diff --git a/Sources/BackupFeature/Controllers/BackupController.swift b/Sources/BackupFeature/Controllers/BackupController.swift
index b01e3865f6aee5765f0cdb18423b553c266de428..ca82c50e8c1d470f1c0433f16e3a6d182ddd0604 100644
--- a/Sources/BackupFeature/Controllers/BackupController.swift
+++ b/Sources/BackupFeature/Controllers/BackupController.swift
@@ -1,4 +1,3 @@
-import DI
 import UIKit
 import Shared
 import Combine
diff --git a/Sources/BackupFeature/Controllers/BackupPassphraseController.swift b/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
index 9ec594c8680d4bc8162cfbc47c077bbbea26b127..35b97b35cab02ea52f5bc5b9f800ccca3a4cba17 100644
--- a/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
+++ b/Sources/BackupFeature/Controllers/BackupPassphraseController.swift
@@ -17,13 +17,13 @@ public final class BackupPassphraseController: UIViewController {
     }
   }
 
-  private let cancelClosure: EmptyClosure
-  private let stringClosure: StringClosure
+  private let cancelClosure: () -> Void
+  private let stringClosure: (String) -> Void
   private var cancellables = Set<AnyCancellable>()
 
   public init(
-    _ cancelClosure: @escaping EmptyClosure,
-    _ stringClosure: @escaping StringClosure
+    _ cancelClosure: @escaping () -> Void,
+    _ stringClosure: @escaping (String) -> Void
   ) {
     self.stringClosure = stringClosure
     self.cancelClosure = cancelClosure
diff --git a/Sources/BackupFeature/Controllers/BackupSetupController.swift b/Sources/BackupFeature/Controllers/BackupSetupController.swift
index efb0cab4a130ed620275c19319eb5302f4638624..7e697535ebfba84a6ef932e582882f89cc8718eb 100644
--- a/Sources/BackupFeature/Controllers/BackupSetupController.swift
+++ b/Sources/BackupFeature/Controllers/BackupSetupController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Combine
-import DI
 
 final class BackupSetupController: UIViewController {
     private lazy var screenView = BackupSetupView()
diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift
index c471287bad37f16d3cda7d81dfb7ff4f1fcc0f07..c024227d5e77cc240f456052e6b4cc96beff4543 100644
--- a/Sources/BackupFeature/Service/BackupService.swift
+++ b/Sources/BackupFeature/Service/BackupService.swift
@@ -10,8 +10,8 @@ import XXMessengerClient
 import ComposableArchitecture
 
 public final class BackupService {
-  @Dependency(\.app.messenger) var messenger: Messenger
-  @Dependency(\.app.networkMonitor) var networkMonitor: NetworkMonitorManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.app.networkMonitor) var networkMonitor
 
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
@@ -255,3 +255,4 @@ public final class BackupService {
       .appendingPathExtension("xxm")
   }
 }
+
diff --git a/Sources/BackupFeature/Service/Dependency.swift b/Sources/BackupFeature/Service/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9d2b0df290ff5e9e90937473f0e6e4ccd0d26955
--- /dev/null
+++ b/Sources/BackupFeature/Service/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum BackupServiceDependencyKey: DependencyKey {
+  static let liveValue: BackupService = .init()
+  static let testValue: BackupService = .init()
+}
+
+extension DependencyValues {
+  public var backupService: BackupService {
+    get { self[BackupServiceDependencyKey.self] }
+    set { self[BackupServiceDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
index 5318952dcadddd6a33bf7c257a4d51ae96851523..410535e63a8f348ef7882aa9dfad4bd90674ae4a 100644
--- a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
@@ -5,7 +5,7 @@ import Combine
 import XXClient
 import Defaults
 import CloudFiles
-import Navigation
+import AppNavigation
 import ComposableArchitecture
 
 enum BackupActionState {
@@ -32,8 +32,8 @@ struct BackupConfigViewModel {
 extension BackupConfigViewModel {
   static func live() -> Self {
     class Context {
-      //@Dependency var service: BackupService
       @Dependency(\.navigator) var navigator: Navigator
+      @Dependency(\.backupService) var service: BackupService
       @Dependency(\.app.hudManager) var hudManager: HUDManager
     }
 
@@ -42,9 +42,9 @@ extension BackupConfigViewModel {
     return .init(
       didTapBackupNow: {
         context.service.didForceBackup()
-        context.hudController.show()
+        context.hudManager.show()
         DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
-          context.hudController.dismiss()
+          context.hudManager.hide()
         }
       },
       didChooseWifiOnly: context.service.didSetWiFiOnly(enabled:),
@@ -58,12 +58,12 @@ extension BackupConfigViewModel {
         context.navigator.perform(PresentPassphrase(onCancel: {
           context.service.toggle(service: service, enabling: false)
         }, onPassphrase: { passphrase in
-          context.hudController.show(.init(
+          context.hudManager.show(.init(
             content: "Initializing and securing your backup file will take few seconds, please keep the app open."
           ))
           context.service.toggle(service: service, enabling: enabling)
           context.service.initializeBackup(passphrase: passphrase)
-          context.hudController.dismiss()
+          context.hudManager.hide()
         }))
       },
       didTapService: { service, controller in
diff --git a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
index 80cdb78497baf010eb0e64c04b53660595af35a9..bd18ee5f294fafcdf2ad8d28eb8465b36429f916 100644
--- a/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupSFTPViewModel.swift
@@ -6,7 +6,9 @@ import Combine
 import Foundation
 import CloudFiles
 import CloudFilesSFTP
-import DI
+
+import AppCore
+import ComposableArchitecture
 
 struct SFTPViewState {
   var host: String = ""
@@ -16,7 +18,7 @@ struct SFTPViewState {
 }
 
 final class BackupSFTPViewModel {
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
 
   var statePublisher: AnyPublisher<SFTPViewState, Never> {
     stateSubject.eraseToAnyPublisher()
@@ -45,7 +47,7 @@ final class BackupSFTPViewModel {
   }
 
   func didTapLogin() {
-    hudController.show()
+    hudManager.show()
 
     let host = stateSubject.value.host
     let username = stateSubject.value.username
@@ -64,7 +66,7 @@ final class BackupSFTPViewModel {
         ).link(anyController) {
           switch $0 {
           case .success:
-            self.hudController.dismiss()
+            self.hudManager.hide()
             self.authSubject.send((host, username, password))
           case .failure(let error):
             var message = "An error occurred while trying to link SFTP: "
@@ -81,11 +83,11 @@ final class BackupSFTPViewModel {
               message.append(error.localizedDescription)
             }
 
-            self.hudController.show(.init(content: message))
+            self.hudManager.show(.init(content: message))
           }
         }
       } catch {
-        self.hudController.show(.init(error: error))
+        self.hudManager.show(.init(error: error))
       }
     }
   }
diff --git a/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift b/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
index 35575aff0578c40a0f57b419740fb7ca5fe3bda1..a470e6c647c987e1af9668fe3a57807075377980 100644
--- a/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupSetupViewModel.swift
@@ -2,19 +2,19 @@ import UIKit
 import Shared
 import Combine
 import CloudFiles
-import DI
+import ComposableArchitecture
 
 struct BackupSetupViewModel {
-    var didTapService: (CloudService, UIViewController) -> Void
+  var didTapService: (CloudService, UIViewController) -> Void
 }
 
 extension BackupSetupViewModel {
-    static func live() -> Self {
-        class Context {
-            @Dependency var service: BackupService
-        }
-
-        let context = Context()
-        return .init(didTapService: context.service.authorize)
+  static func live() -> Self {
+    class Context {
+      @Dependency(\.backupService) var service: BackupService
     }
+
+    let context = Context()
+    return .init(didTapService: context.service.authorize)
+  }
 }
diff --git a/Sources/BackupFeature/ViewModels/BackupViewModel.swift b/Sources/BackupFeature/ViewModels/BackupViewModel.swift
index d25ddc5ebfbd3778131f15b111ad57e89f4c6733..378590c3edadce9b7036e2f262fcedc6f36c9626 100644
--- a/Sources/BackupFeature/ViewModels/BackupViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupViewModel.swift
@@ -1,5 +1,5 @@
-import DI
 import Combine
+import ComposableArchitecture
 
 enum BackupViewState: Equatable {
   case setup
@@ -16,7 +16,7 @@ struct BackupViewModel {
 extension BackupViewModel {
   static func live() -> Self {
     class Context {
-      @Dependency var service: BackupService
+      @Dependency(\.backupService) var service: BackupService
     }
 
     let context = Context()
diff --git a/Sources/ChatFeature/CellFactory.swift b/Sources/ChatFeature/CellFactory.swift
index bc7bc9bec131565d07dc5805865bdcc13e0959dc..2f7767ebe4902933f0615d000ca48e6ebf9ed8ee 100644
--- a/Sources/ChatFeature/CellFactory.swift
+++ b/Sources/ChatFeature/CellFactory.swift
@@ -1,76 +1,76 @@
-import UIKit
-import XCTestDynamicOverlay
-
-public struct CellFactory<Model> {
-  public struct Registrar {
-    public init(register: @escaping (UICollectionView) -> Void) {
-      self.register = register
-    }
-
-    public var register: (UICollectionView) -> Void
-
-    public func callAsFunction(in view: UICollectionView) {
-      register(view)
-    }
-  }
-
-  public struct Builder {
-    public init(build: @escaping (Model, UICollectionView, IndexPath) -> UICollectionViewCell?) {
-      self.build = build
-    }
-
-    public var build: (Model, UICollectionView, IndexPath) -> UICollectionViewCell?
-
-    public func callAsFunction(
-      for model: Model,
-      in view: UICollectionView,
-      at indexPath: IndexPath
-    ) -> UICollectionViewCell? {
-      build(model, view, indexPath)
-    }
-  }
-
-  public init(
-    register: Registrar,
-    build: Builder
-  ) {
-    self.register = register
-    self.build = build
-  }
-
-  public var register: Registrar
-  public var build: Builder
-}
-
-extension CellFactory {
-  public static func combined(_ factories: CellFactory...) -> CellFactory {
-    combined(factories)
-  }
-
-  public static func combined(_ factories: [CellFactory]) -> CellFactory {
-    CellFactory(
-      register: .init { collectionView in
-        factories.forEach { $0.register(in: collectionView) }
-      },
-      build: .init { model, collectionView, indexPath in
-        for factory in factories {
-          if let cell = factory.build(for: model, in: collectionView, at: indexPath) {
-            return cell
-          }
-        }
-        return nil
-      }
-    )
-  }
-}
-
-#if DEBUG
-extension CellFactory {
-  public static func unimplemented() -> CellFactory {
-    CellFactory(
-      register: .init(register: XCTUnimplemented("\(Self.self).Registrar")),
-      build: .init(build: XCTUnimplemented("\(Self.self).Builder"))
-    )
-  }
-}
-#endif
+//import UIKit
+//import XCTestDynamicOverlay
+//
+//public struct CellFactory<Model> {
+//  public struct Registrar {
+//    public init(register: @escaping (UICollectionView) -> Void) {
+//      self.register = register
+//    }
+//
+//    public var register: (UICollectionView) -> Void
+//
+//    public func callAsFunction(in view: UICollectionView) {
+//      register(view)
+//    }
+//  }
+//
+//  public struct Builder {
+//    public init(build: @escaping (Model, UICollectionView, IndexPath) -> UICollectionViewCell?) {
+//      self.build = build
+//    }
+//
+//    public var build: (Model, UICollectionView, IndexPath) -> UICollectionViewCell?
+//
+//    public func callAsFunction(
+//      for model: Model,
+//      in view: UICollectionView,
+//      at indexPath: IndexPath
+//    ) -> UICollectionViewCell? {
+//      build(model, view, indexPath)
+//    }
+//  }
+//
+//  public init(
+//    register: Registrar,
+//    build: Builder
+//  ) {
+//    self.register = register
+//    self.build = build
+//  }
+//
+//  public var register: Registrar
+//  public var build: Builder
+//}
+//
+//extension CellFactory {
+//  public static func combined(_ factories: CellFactory...) -> CellFactory {
+//    combined(factories)
+//  }
+//
+//  public static func combined(_ factories: [CellFactory]) -> CellFactory {
+//    CellFactory(
+//      register: .init { collectionView in
+//        factories.forEach { $0.register(in: collectionView) }
+//      },
+//      build: .init { model, collectionView, indexPath in
+//        for factory in factories {
+//          if let cell = factory.build(for: model, in: collectionView, at: indexPath) {
+//            return cell
+//          }
+//        }
+//        return nil
+//      }
+//    )
+//  }
+//}
+//
+//#if DEBUG
+//extension CellFactory {
+//  public static func unimplemented() -> CellFactory {
+//    CellFactory(
+//      register: .init(register: XCTUnimplemented("\(Self.self).Registrar")),
+//      build: .init(build: XCTUnimplemented("\(Self.self).Builder"))
+//    )
+//  }
+//}
+//#endif
diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift
index 7a5090ef483860e517d5f128dfcc8e758d86d4b8..43ed50008506da291cc8d9233bd468423e4ad8b3 100644
--- a/Sources/ChatFeature/Controllers/GroupChatController.swift
+++ b/Sources/ChatFeature/Controllers/GroupChatController.swift
@@ -1,11 +1,13 @@
-import DI
 import UIKit
 import Shared
 import Combine
+import AppCore
 import XXModels
 import Voxophone
 import ChatLayout
-import Navigation
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
 import DifferenceKit
 import ReportingFeature
@@ -19,12 +21,13 @@ typealias OutgoingFailedGroupTextCell = CollectionCell<FlexibleSpace, StackMessa
 typealias OutgoingFailedGroupReplyCell = CollectionCell<FlexibleSpace, ReplyStackMessageView>
 
 public final class GroupChatController: UIViewController {
-  @Dependency var database: Database
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var makeReportDrawer: MakeReportDrawer
-  @Dependency var makeAppScreenshot: MakeAppScreenshot
+  @Dependency(\.navigator) var navigator
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.statusBar) var statusBar
+  @Dependency(\.reportingStatus) var reportingStatus
+
+//  @Dependency var makeReportDrawer: MakeReportDrawer
+//  @Dependency var makeAppScreenshot: MakeAppScreenshot
 
   private var collectionView: UICollectionView!
   private lazy var header = GroupHeaderView()
@@ -50,7 +53,7 @@ public final class GroupChatController: UIViewController {
       initialState: .init(canAddAttachments: false),
       reducer: chatInputReducer,
       environment: .init(
-        voxophone: try! DI.Container.shared.resolve() as Voxophone,
+        voxophone: Voxophone(), //try! DI.Container.shared.resolve() as Voxophone,
         sendAudio: { _ in },
         didTapCamera: {},
         didTapLibrary: {},
@@ -76,7 +79,7 @@ public final class GroupChatController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(
       backgroundColor: Asset.neutralWhite.color,
       shadowColor: Asset.neutralDisabled.color
@@ -199,7 +202,7 @@ public final class GroupChatController: UIViewController {
           ], isDismissable: false, from: self))
 
         case .webview(let urlString):
-          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
+          navigator.perform(PresentWebsite(urlString: urlString, from: self))
         }
       }.store(in: &cancellables)
 
@@ -222,10 +225,10 @@ public final class GroupChatController: UIViewController {
             navigator.perform(DismissModal(from: self)) { [weak self] in
               guard let self else { return }
               self.drawerCancellables.removeAll()
-              let screenshot = try! self.makeAppScreenshot()
-              self.viewModel.report(contact: contact, screenshot: screenshot) {
-                self.collectionView.reloadData()
-              }
+//              let screenshot = try! self.makeAppScreenshot()
+//              self.viewModel.report(contact: contact, screenshot: screenshot) {
+//                self.collectionView.reloadData()
+//              }
             }
           }.store(in: &drawerCancellables)
 
@@ -392,7 +395,7 @@ extension GroupChatController: UICollectionViewDataSource {
 
     var isSenderBanned = false
 
-    if let sender = try? database.fetchContacts(.init(id: [item.senderId])).first {
+    if let sender = try? dbManager.getDB().fetchContacts(.init(id: [item.senderId])).first {
       isSenderBanned = sender.isBanned
     }
 
@@ -640,7 +643,10 @@ extension GroupChatController: UICollectionViewDelegate {
       previewProvider: nil
     ) { [weak self] suggestedActions in
 
-      guard let self else { return nil }
+      guard let self else {
+        fatalError()
+        //return nil
+      }
 
       let item = self.sections[indexPath.section].elements[indexPath.item]
 
diff --git a/Sources/ChatFeature/Controllers/MembersController.swift b/Sources/ChatFeature/Controllers/MembersController.swift
index 435ec4dfb63beb7869794dc51e15566942b6a16b..086114eaafc2da90ceec2c80a61d926d255d62c9 100644
--- a/Sources/ChatFeature/Controllers/MembersController.swift
+++ b/Sources/ChatFeature/Controllers/MembersController.swift
@@ -1,82 +1,83 @@
 import UIKit
 import Shared
 import XXModels
+import AppResources
 
 final class MembersController: UIViewController {
-    private lazy var stackView = UIStackView()
-
-    private let members: [Contact]
-
-    init(with members: [Contact]) {
-        self.members = members
-        super.init(nibName: nil, bundle: nil)
+  private lazy var stackView = UIStackView()
+  
+  private let members: [Contact]
+  
+  init(with members: [Contact]) {
+    self.members = members
+    super.init(nibName: nil, bundle: nil)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    
+    view.layer.cornerRadius = 15
+    view.layer.masksToBounds = true
+    view.backgroundColor = Asset.neutralWhite.color
+    
+    stackView.axis = .vertical
+    stackView.distribution = .fillEqually
+    view.addSubview(stackView)
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(10)
+      $0.left.right.equalToSuperview()
+      $0.bottom.equalTo(view.safeAreaLayoutGuide)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-
-        view.layer.cornerRadius = 15
-        view.layer.masksToBounds = true
-        view.backgroundColor = Asset.neutralWhite.color
-
-        stackView.axis = .vertical
-        stackView.distribution = .fillEqually
-        view.addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(10)
-            $0.left.right.equalToSuperview()
-            $0.bottom.equalTo(view.safeAreaLayoutGuide)
-        }
-
-        members.forEach {
-            let memberView = MemberView()
-            let assignedTitle = ($0.nickname ?? $0.username) ?? "Fetching username..."
-            memberView.titleLabel.text = assignedTitle
-            memberView.avatarView.setupProfile(title: assignedTitle, image: $0.photo, size: .small)
-            stackView.addArrangedSubview(memberView)
-        }
+    
+    members.forEach {
+      let memberView = MemberView()
+      let assignedTitle = ($0.nickname ?? $0.username) ?? "Fetching username..."
+      memberView.titleLabel.text = assignedTitle
+      memberView.avatarView.setupProfile(title: assignedTitle, image: $0.photo, size: .small)
+      stackView.addArrangedSubview(memberView)
     }
+  }
 }
 
 private final class MemberView: UIView {
-    let titleLabel = UILabel()
-    let avatarView = AvatarView()
-    let separatorView = UIView()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-        titleLabel.textColor = Asset.neutralBody.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        addSubview(titleLabel)
-        addSubview(avatarView)
-        addSubview(separatorView)
-
-        avatarView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(10)
-            $0.width.height.equalTo(30)
-            $0.left.equalToSuperview().offset(25)
-            $0.centerY.equalToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.centerY.equalTo(avatarView)
-            $0.left.equalTo(avatarView.snp.right).offset(14)
-            $0.right.lessThanOrEqualToSuperview().offset(-10)
-        }
-
-        separatorView.snp.makeConstraints {
-            $0.height.equalTo(1)
-            $0.left.equalToSuperview().offset(25)
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  let avatarView = AvatarView()
+  let separatorView = UIView()
+  
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    titleLabel.textColor = Asset.neutralBody.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    separatorView.backgroundColor = Asset.neutralLine.color
+    
+    addSubview(titleLabel)
+    addSubview(avatarView)
+    addSubview(separatorView)
+    
+    avatarView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(10)
+      $0.width.height.equalTo(30)
+      $0.left.equalToSuperview().offset(25)
+      $0.centerY.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    titleLabel.snp.makeConstraints {
+      $0.centerY.equalTo(avatarView)
+      $0.left.equalTo(avatarView.snp.right).offset(14)
+      $0.right.lessThanOrEqualToSuperview().offset(-10)
+    }
+    
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview().offset(25)
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index a8052cb16ae611a98ff44c37c29102e1fc442701..4ae089ad95fab266d3300d0f73c1b19345e59c81 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -1,15 +1,15 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import XXLogger
+import AppCore
 import XXModels
 import QuickLook
 import Voxophone
-import Navigation
 import ChatLayout
-import Navigation
+import Dependencies
+import AppResources
 import DrawerFeature
+import AppNavigation
 import DifferenceKit
 import ChatInputFeature
 import ReportingFeature
@@ -24,13 +24,15 @@ extension Message: Differentiable {
 }
 
 public final class SingleChatController: UIViewController {
-  @Dependency var logger: XXLogger
-  @Dependency var navigator: Navigator
-  @Dependency var voxophone: Voxophone
-  @Dependency var barStylist: StatusBarStylist
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var makeReportDrawer: MakeReportDrawer
-  @Dependency var makeAppScreenshot: MakeAppScreenshot
+//  @Dependency var voxophone: Voxophone
+//  @Dependency var makeReportDrawer: MakeReportDrawer
+//  @Dependency var makeAppScreenshot: MakeAppScreenshot
+
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  let voxophone = Voxophone()
 
   private lazy var infoView = UIControl()
   private lazy var nameLabel = UILabel()
@@ -66,7 +68,7 @@ public final class SingleChatController: UIViewController {
       initialState: .init(canAddAttachments: true),
       reducer: chatInputReducer,
       environment: .init(
-        voxophone: try! DI.Container.shared.resolve() as Voxophone,
+        voxophone: Voxophone(), //try! DI.Container.shared.resolve() as Voxophone,
         sendAudio: { viewModel.didSendAudio(url: $0) },
         didTapCamera: { viewModel.didTest(permission: .camera) },
         didTapLibrary: { viewModel.didTest(permission: .library) },
@@ -83,7 +85,7 @@ public final class SingleChatController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(
       backgroundColor: Asset.neutralWhite.color,
       shadowColor: Asset.neutralDisabled.color
@@ -213,49 +215,49 @@ public final class SingleChatController: UIViewController {
     viewModel.navigation
       .receive(on: DispatchQueue.main)
       .removeDuplicates()
-      .sink { [unowned self] _ in
-//        switch $0 {
-//        case .library:
-//          navigator.perform(PresentPhotoLibrary())
-//        case .camera:
-//          navigator.perform(PresentCamera())
-//        case .cameraPermission:
-//          navigator.perform(PresentPermissionRequest(type: .camera))
-//        case .microphonePermission:
-//          navigator.perform(PresentPermissionRequest(type: .microphone))
-//        case .libraryPermission:
-//          navigator.perform(PresentPermissionRequest(type: .library))
-//        case .webview(let urlString):
-//          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
-//        case .waitingRound:
-//          let button = DrawerCapsuleButton(model: .init(
-//            title: Localized.Chat.RoundDrawer.action,
-//            style: .brandColored
-//          ))
-//
-//          button
-//            .action
-//            .receive(on: DispatchQueue.main)
-//            .sink { [unowned self] in
-//              navigator.perform(DismissModal(from: self)) { [weak self] in
-//                guard let self else { return }
-//                self.drawerCancellables.removeAll()
-//              }
-//            }.store(in: &drawerCancellables)
-//
-//          navigator.perform(PresentDrawer(items: [
-//            DrawerText(
-//              font: Fonts.Mulish.semiBold.font(size: 14.0),
-//              text: Localized.Chat.RoundDrawer.title,
-//              color: Asset.neutralWeak.color,
-//              lineHeightMultiple: 1.35,
-//              spacingAfter: 25
-//            ),
-//            button
-//          ]))
-//        case .none:
-//          break
-//        }
+      .sink { [unowned self] in
+        switch $0 {
+        case .library:
+          navigator.perform(PresentPhotoLibrary(from: self))
+        case .camera:
+          navigator.perform(PresentCamera(from: self))
+        case .cameraPermission:
+          navigator.perform(PresentPermissionRequest(type: .camera, from: self))
+        case .microphonePermission:
+          navigator.perform(PresentPermissionRequest(type: .microphone, from: self))
+        case .libraryPermission:
+          navigator.perform(PresentPermissionRequest(type: .library, from: self))
+        case .webview(let urlString):
+          navigator.perform(PresentWebsite(urlString: urlString, from: self))
+        case .waitingRound:
+          let button = DrawerCapsuleButton(model: .init(
+            title: Localized.Chat.RoundDrawer.action,
+            style: .brandColored
+          ))
+
+          button
+            .action
+            .receive(on: DispatchQueue.main)
+            .sink { [unowned self] in
+              navigator.perform(DismissModal(from: self)) { [weak self] in
+                guard let self else { return }
+                self.drawerCancellables.removeAll()
+              }
+            }.store(in: &drawerCancellables)
+
+          navigator.perform(PresentDrawer(items: [
+            DrawerText(
+              font: Fonts.Mulish.semiBold.font(size: 14.0),
+              text: Localized.Chat.RoundDrawer.title,
+              color: Asset.neutralWeak.color,
+              lineHeightMultiple: 1.35,
+              spacingAfter: 25
+            ),
+            button
+          ], isDismissable: true, from: self))
+        case .none:
+          break
+        }
 
         viewModel.didNavigateSomewhere()
       }.store(in: &cancellables)
@@ -408,11 +410,11 @@ public final class SingleChatController: UIViewController {
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self else { return }
           self.drawerCancellables.removeAll()
-          let screenshot = try! self.makeAppScreenshot()
-          self.viewModel.report(screenshot: screenshot) { success in
-            guard success else { return }
-            self.navigationController?.popViewController(animated: true)
-          }
+//          let screenshot = try! self.makeAppScreenshot()
+//          self.viewModel.report(screenshot: screenshot) { success in
+//            guard success else { return }
+//            self.navigationController?.popViewController(animated: true)
+//          }
         }
       }.store(in: &drawerCancellables)
 
diff --git a/Sources/ChatFeature/Controllers/WebController.swift b/Sources/ChatFeature/Controllers/WebController.swift
deleted file mode 100644
index f3099b7a5bcb8cea0b867f5cbdeeb9e5327f8b46..0000000000000000000000000000000000000000
--- a/Sources/ChatFeature/Controllers/WebController.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-import UIKit
-import WebKit
-
-public final class WebScreen: UIViewController {
-  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 }
-  }
-
-  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()
-    }
-    webView.snp.makeConstraints {
-      $0.bottom.equalToSuperview()
-      $0.left.equalToSuperview()
-      $0.right.equalToSuperview()
-      $0.top.equalTo(navBar.snp.bottom)
-    }
-  }
-
-  required init?(coder: NSCoder) { nil }
-}
diff --git a/Sources/ChatFeature/Helpers/BubbleBuilder.swift b/Sources/ChatFeature/Helpers/BubbleBuilder.swift
index e6d71c81ee3557385b2d9ec3e349ece13948ac33..e9e53d9355f380032cf7e835c7c8531a85c8233c 100644
--- a/Sources/ChatFeature/Helpers/BubbleBuilder.swift
+++ b/Sources/ChatFeature/Helpers/BubbleBuilder.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import XXModels
+import AppResources
 
 final class Bubbler {
     static func build(
diff --git a/Sources/ChatFeature/Helpers/CellConfigurator.swift b/Sources/ChatFeature/Helpers/CellConfigurator.swift
index d9b61fd9d3be46405ab170259dbe82aa0b1961a0..63b7998cc93808fe34d6d97d32f6c9ddecb903e2 100644
--- a/Sources/ChatFeature/Helpers/CellConfigurator.swift
+++ b/Sources/ChatFeature/Helpers/CellConfigurator.swift
@@ -3,442 +3,443 @@ import Shared
 import Combine
 import XXModels
 import Voxophone
+import AppResources
 import AVFoundation
 
 struct CellFactory {
-    var canBuild: (Message) -> Bool
-
-    var build: (Message, UICollectionView, IndexPath) -> UICollectionViewCell
-
-    func callAsFunction(
-        item: Message,
-        collectionView: UICollectionView,
-        indexPath: IndexPath
-    ) -> UICollectionViewCell {
-        build(item, collectionView, indexPath)
-    }
+  var canBuild: (Message) -> Bool
+  
+  var build: (Message, UICollectionView, IndexPath) -> UICollectionViewCell
+  
+  func callAsFunction(
+    item: Message,
+    collectionView: UICollectionView,
+    indexPath: IndexPath
+  ) -> UICollectionViewCell {
+    build(item, collectionView, indexPath)
+  }
 }
 
 extension CellFactory {
-    static func combined(factories: [CellFactory]) -> Self {
-        .init(
-            canBuild: { _ in true },
-            build: { item, collectionView, indexPath in
-                guard let factory = factories.first(where: { $0.canBuild(item)}) else {
-                    fatalError("Couldn't find a factory for \(item). Did you forget to implement?")
-                }
-
-                return factory(
-                    item: item,
-                    collectionView: collectionView,
-                    indexPath: indexPath
-                )
-            }
+  static func combined(factories: [CellFactory]) -> Self {
+    .init(
+      canBuild: { _ in true },
+      build: { item, collectionView, indexPath in
+        guard let factory = factories.first(where: { $0.canBuild(item)}) else {
+          fatalError("Couldn't find a factory for \(item). Did you forget to implement?")
+        }
+        
+        return factory(
+          item: item,
+          collectionView: collectionView,
+          indexPath: indexPath
         )
-    }
+      }
+    )
+  }
 }
 
 extension CellFactory {
-    static func incomingAudio(
-        voxophone: Voxophone,
-        transfer: @escaping (Data) -> FileTransfer
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                guard (item.status == .received || item.status == .receiving),
-                      item.replyMessageId == nil,
-                      item.fileTransferId != nil else { return false }
-
-                return transfer(item.fileTransferId!).type == "m4a"
-
-            }, build: { item, collectionView, indexPath in
-                let ft = transfer(item.fileTransferId!)
-                let cell: IncomingAudioCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-                let url = FileManager.url(for: "\(ft.name).\(ft.type)")!
-
-                var model = AudioMessageCellState(
-                    date: item.date,
-                    audioURL: url,
-                    isPlaying: false,
-                    transferProgress: ft.progress,
-                    isLoudspeaker: false,
-                    duration: (try? AVAudioPlayer(contentsOf: url).duration) ?? 0.0,
-                    playbackTime: 0.0
-                )
-
-                cell.leftView.setup(with: model)
-                cell.canReply = false
-                cell.performReply = {}
-
-                Bubbler.build(audioBubble: cell.leftView, with: item)
-
-                voxophone.$state
-                    .sink {
-                        switch $0 {
-                        case .playing(url, _, time: let time, _):
-                            model.isPlaying = true
-                            model.playbackTime = time
-                        default:
-                            model.isPlaying = false
-                            model.playbackTime = 0.0
-                        }
-
-                        model.isLoudspeaker = $0.isLoudspeaker
-
-                        cell.leftView.setup(with: model)
-                    }.store(in: &cell.leftView.cancellables)
-
-                cell.leftView.didTapRight = {
-                    guard item.status != .receiving else { return }
-
-                    voxophone.toggleLoudspeaker()
-                }
-
-                cell.leftView.didTapLeft = {
-                    guard item.status != .receiving else { return }
-
-                    if case .playing(url, _, _, _) = voxophone.state {
-                        voxophone.reset()
-                    } else {
-                        voxophone.load(url)
-                        voxophone.play()
-                    }
-                }
-
-                return cell
-            }
+  static func incomingAudio(
+    voxophone: Voxophone,
+    transfer: @escaping (Data) -> FileTransfer
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        guard (item.status == .received || item.status == .receiving),
+              item.replyMessageId == nil,
+              item.fileTransferId != nil else { return false }
+        
+        return transfer(item.fileTransferId!).type == "m4a"
+        
+      }, build: { item, collectionView, indexPath in
+        let ft = transfer(item.fileTransferId!)
+        let cell: IncomingAudioCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        let url = FileManager.url(for: "\(ft.name).\(ft.type)")!
+        
+        var model = AudioMessageCellState(
+          date: item.date,
+          audioURL: url,
+          isPlaying: false,
+          transferProgress: ft.progress,
+          isLoudspeaker: false,
+          duration: (try? AVAudioPlayer(contentsOf: url).duration) ?? 0.0,
+          playbackTime: 0.0
         )
-    }
-
-    static func outgoingAudio(
-        voxophone: Voxophone,
-        transfer: @escaping (Data) -> FileTransfer
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                guard (item.status == .sent ||
-                       item.status == .sending ||
-                       item.status == .sendingFailed ||
-                       item.status == .sendingTimedOut)
-                        && item.replyMessageId == nil
-                        && item.fileTransferId != nil else {
-                    return false
-                }
-
-                return transfer(item.fileTransferId!).type == "m4a"
-
-            }, build: { item, collectionView, indexPath in
-                let ft = transfer(item.fileTransferId!)
-                let cell: OutgoingAudioCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-                let url = FileManager.url(for: "\(ft.name).\(ft.type)")!
-                var model = AudioMessageCellState(
-                    date: item.date,
-                    audioURL: url,
-                    isPlaying: false,
-                    transferProgress: ft.progress,
-                    isLoudspeaker: false,
-                    duration: (try? AVAudioPlayer(contentsOf: url).duration) ?? 0.0,
-                    playbackTime: 0.0
-                )
-
-                cell.rightView.setup(with: model)
-                cell.canReply = false
-                cell.performReply = {}
-
-                Bubbler.build(audioBubble: cell.rightView, with: item)
-
-                voxophone.$state
-                    .sink {
-                        switch $0 {
-                        case .playing(url, _, time: let time, _):
-                            model.isPlaying = true
-                            model.playbackTime = time
-                        default:
-                            model.isPlaying = false
-                            model.playbackTime = 0.0
-                        }
-
-                        model.isLoudspeaker = $0.isLoudspeaker
-
-                        cell.rightView.setup(with: model)
-                    }.store(in: &cell.rightView.cancellables)
-
-                cell.rightView.didTapRight = {
-                    voxophone.toggleLoudspeaker()
-                }
-
-                cell.rightView.didTapLeft = {
-                    if case .playing(url, _, _, _) = voxophone.state {
-                        voxophone.reset()
-                    } else {
-                        voxophone.load(url)
-                        voxophone.play()
-                    }
-                }
-
-                return cell
+        
+        cell.leftView.setup(with: model)
+        cell.canReply = false
+        cell.performReply = {}
+        
+        Bubbler.build(audioBubble: cell.leftView, with: item)
+        
+        voxophone.$state
+          .sink {
+            switch $0 {
+            case .playing(url, _, time: let time, _):
+              model.isPlaying = true
+              model.playbackTime = time
+            default:
+              model.isPlaying = false
+              model.playbackTime = 0.0
             }
+            
+            model.isLoudspeaker = $0.isLoudspeaker
+            
+            cell.leftView.setup(with: model)
+          }.store(in: &cell.leftView.cancellables)
+        
+        cell.leftView.didTapRight = {
+          guard item.status != .receiving else { return }
+          
+          voxophone.toggleLoudspeaker()
+        }
+        
+        cell.leftView.didTapLeft = {
+          guard item.status != .receiving else { return }
+          
+          if case .playing(url, _, _, _) = voxophone.state {
+            voxophone.reset()
+          } else {
+            voxophone.load(url)
+            voxophone.play()
+          }
+        }
+        
+        return cell
+      }
+    )
+  }
+  
+  static func outgoingAudio(
+    voxophone: Voxophone,
+    transfer: @escaping (Data) -> FileTransfer
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        guard (item.status == .sent ||
+               item.status == .sending ||
+               item.status == .sendingFailed ||
+               item.status == .sendingTimedOut)
+                && item.replyMessageId == nil
+                && item.fileTransferId != nil else {
+          return false
+        }
+        
+        return transfer(item.fileTransferId!).type == "m4a"
+        
+      }, build: { item, collectionView, indexPath in
+        let ft = transfer(item.fileTransferId!)
+        let cell: OutgoingAudioCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        let url = FileManager.url(for: "\(ft.name).\(ft.type)")!
+        var model = AudioMessageCellState(
+          date: item.date,
+          audioURL: url,
+          isPlaying: false,
+          transferProgress: ft.progress,
+          isLoudspeaker: false,
+          duration: (try? AVAudioPlayer(contentsOf: url).duration) ?? 0.0,
+          playbackTime: 0.0
         )
-    }
+        
+        cell.rightView.setup(with: model)
+        cell.canReply = false
+        cell.performReply = {}
+        
+        Bubbler.build(audioBubble: cell.rightView, with: item)
+        
+        voxophone.$state
+          .sink {
+            switch $0 {
+            case .playing(url, _, time: let time, _):
+              model.isPlaying = true
+              model.playbackTime = time
+            default:
+              model.isPlaying = false
+              model.playbackTime = 0.0
+            }
+            
+            model.isLoudspeaker = $0.isLoudspeaker
+            
+            cell.rightView.setup(with: model)
+          }.store(in: &cell.rightView.cancellables)
+        
+        cell.rightView.didTapRight = {
+          voxophone.toggleLoudspeaker()
+        }
+        
+        cell.rightView.didTapLeft = {
+          if case .playing(url, _, _, _) = voxophone.state {
+            voxophone.reset()
+          } else {
+            voxophone.load(url)
+            voxophone.play()
+          }
+        }
+        
+        return cell
+      }
+    )
+  }
 }
 
 extension CellFactory {
-    static func outgoingImage(
-        transfer:  @escaping (Data) -> FileTransfer
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                guard (item.status == .sent ||
-                       item.status == .sending ||
-                       item.status == .sendingFailed ||
-                       item.status == .sendingTimedOut)
-                        && item.replyMessageId == nil
-                        && item.fileTransferId != nil else {
-                    return false
-                }
-
-                return transfer(item.fileTransferId!).type == "jpeg"
-
-            }, build: { item, collectionView, indexPath in
-                let ft = transfer(item.fileTransferId!)
-                let cell: OutgoingImageCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.build(imageBubble: cell.rightView, with: item, with: transfer(item.fileTransferId!))
-                cell.canReply = false
-                cell.performReply = {}
-
-                if let image = UIImage(data: ft.data!) {
-                    cell.rightView.imageView.image = UIImage(cgImage: image.cgImage!, scale: image.scale, orientation: .up)
-                }
-
-                return cell
-            }
-        )
-    }
-
-    static func incomingImage(
-        transfer: @escaping (Data) -> FileTransfer
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                guard (item.status == .received || item.status == .receiving)
-                        && item.replyMessageId == nil
-                        && item.fileTransferId != nil else {
-                    return false
-                }
-
-                return transfer(item.fileTransferId!).type == "jpeg"
-
-            }, build: { item, collectionView, indexPath in
-                let ft = transfer(item.fileTransferId!)
-                let cell: IncomingImageCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.build(imageBubble: cell.leftView, with: item, with: ft)
-                cell.canReply = false
-                cell.performReply = {}
-
-                if let data = ft.data {
-                    cell.leftView.imageView.image = UIImage(data: data)
-                } else {
-                    cell.leftView.imageView.image = Asset.transferImagePlaceholder.image
-                }
-
-                return cell
-            }
-        )
-    }
+  static func outgoingImage(
+    transfer:  @escaping (Data) -> FileTransfer
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        guard (item.status == .sent ||
+               item.status == .sending ||
+               item.status == .sendingFailed ||
+               item.status == .sendingTimedOut)
+                && item.replyMessageId == nil
+                && item.fileTransferId != nil else {
+          return false
+        }
+        
+        return transfer(item.fileTransferId!).type == "jpeg"
+        
+      }, build: { item, collectionView, indexPath in
+        let ft = transfer(item.fileTransferId!)
+        let cell: OutgoingImageCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.build(imageBubble: cell.rightView, with: item, with: transfer(item.fileTransferId!))
+        cell.canReply = false
+        cell.performReply = {}
+        
+        if let image = UIImage(data: ft.data!) {
+          cell.rightView.imageView.image = UIImage(cgImage: image.cgImage!, scale: image.scale, orientation: .up)
+        }
+        
+        return cell
+      }
+    )
+  }
+  
+  static func incomingImage(
+    transfer: @escaping (Data) -> FileTransfer
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        guard (item.status == .received || item.status == .receiving)
+                && item.replyMessageId == nil
+                && item.fileTransferId != nil else {
+          return false
+        }
+        
+        return transfer(item.fileTransferId!).type == "jpeg"
+        
+      }, build: { item, collectionView, indexPath in
+        let ft = transfer(item.fileTransferId!)
+        let cell: IncomingImageCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.build(imageBubble: cell.leftView, with: item, with: ft)
+        cell.canReply = false
+        cell.performReply = {}
+        
+        if let data = ft.data {
+          cell.leftView.imageView.image = UIImage(data: data)
+        } else {
+          cell.leftView.imageView.image = Asset.transferImagePlaceholder.image
+        }
+        
+        return cell
+      }
+    )
+  }
 }
 
 extension CellFactory {
-    static func outgoingReply(
-        performReply: @escaping () -> Void,
-        replyContent: @escaping (Data) -> (String, String),
-        showRound: @escaping (String?) -> Void
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                (item.status == .sent || item.status == .sending)
-                && item.replyMessageId != nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: OutgoingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReply(
-                    bubble: cell.rightView,
-                    with: item,
-                    reply: replyContent(item.replyMessageId!)
-                )
-
-                cell.canReply = item.status == .sent
-                cell.performReply = performReply
-                cell.rightView.didTapShowRound = { showRound(item.roundURL) }
-                return cell
-            }
+  static func outgoingReply(
+    performReply: @escaping () -> Void,
+    replyContent: @escaping (Data) -> (String, String),
+    showRound: @escaping (String?) -> Void
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        (item.status == .sent || item.status == .sending)
+        && item.replyMessageId != nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: OutgoingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.buildReply(
+          bubble: cell.rightView,
+          with: item,
+          reply: replyContent(item.replyMessageId!)
         )
-    }
-
-    static func incomingReply(
-        performReply: @escaping () -> Void,
-        replyContent: @escaping (Data) -> (String, String),
-        showRound: @escaping (String?) -> Void
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                item.status == .received
-                && item.replyMessageId != nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: IncomingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReply(
-                    bubble: cell.leftView,
-                    with: item,
-                    reply: replyContent(item.replyMessageId!)
-                )
-                cell.canReply = item.status == .received
-                cell.performReply = performReply
-                cell.leftView.didTapShowRound = { showRound(item.roundURL) }
-                cell.leftView.revertBottomStackOrder()
-                return cell
-            }
+        
+        cell.canReply = item.status == .sent
+        cell.performReply = performReply
+        cell.rightView.didTapShowRound = { showRound(item.roundURL) }
+        return cell
+      }
+    )
+  }
+  
+  static func incomingReply(
+    performReply: @escaping () -> Void,
+    replyContent: @escaping (Data) -> (String, String),
+    showRound: @escaping (String?) -> Void
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        item.status == .received
+        && item.replyMessageId != nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: IncomingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.buildReply(
+          bubble: cell.leftView,
+          with: item,
+          reply: replyContent(item.replyMessageId!)
         )
-    }
-
-    static func outgoingFailedReply(
-        performReply: @escaping () -> Void,
-        replyContent: @escaping (Data) -> (String, String)
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                (item.status == .sendingFailed || item.status == .sendingTimedOut)
-                && item.replyMessageId != nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: OutgoingFailedReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.buildReply(
-                    bubble: cell.rightView,
-                    with: item,
-                    reply: replyContent(item.replyMessageId!)
-                )
-
-                cell.canReply = false
-                cell.performReply = performReply
-                return cell
-            }
+        cell.canReply = item.status == .received
+        cell.performReply = performReply
+        cell.leftView.didTapShowRound = { showRound(item.roundURL) }
+        cell.leftView.revertBottomStackOrder()
+        return cell
+      }
+    )
+  }
+  
+  static func outgoingFailedReply(
+    performReply: @escaping () -> Void,
+    replyContent: @escaping (Data) -> (String, String)
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        (item.status == .sendingFailed || item.status == .sendingTimedOut)
+        && item.replyMessageId != nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: OutgoingFailedReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.buildReply(
+          bubble: cell.rightView,
+          with: item,
+          reply: replyContent(item.replyMessageId!)
         )
-    }
+        
+        cell.canReply = false
+        cell.performReply = performReply
+        return cell
+      }
+    )
+  }
 }
 
 extension CellFactory {
-    static func incomingText(
-        performReply: @escaping () -> Void,
-        showRound: @escaping (String?) -> Void
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                item.status == .received
-                && item.replyMessageId == nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: IncomingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.build(bubble: cell.leftView, with: item)
-                cell.canReply = item.status == .received
-                cell.performReply = performReply
-                cell.leftView.didTapShowRound = { showRound(item.roundURL) }
-                cell.leftView.revertBottomStackOrder()
-                return cell
-            }
-        )
-    }
-
-    static func outgoingText(
-        performReply: @escaping () -> Void,
-        showRound: @escaping (String?) -> Void
-    ) -> Self {
-        .init(
-            canBuild: { item in
-                (item.status == .sending || item.status == .sent)
-                && item.replyMessageId == nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: OutgoingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.build(bubble: cell.rightView, with: item)
-                cell.canReply = item.status == .sent
-                cell.performReply = performReply
-                cell.rightView.didTapShowRound = { showRound(item.roundURL) }
-
-                return cell
-            }
-        )
-    }
-
-    static func outgoingFailedText(performReply: @escaping () -> Void) -> Self {
-        .init(
-            canBuild: { item in
-                (item.status == .sendingFailed || item.status == .sendingTimedOut)
-                && item.replyMessageId == nil
-
-            }, build: { item, collectionView, indexPath in
-                let cell: OutgoingFailedTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
-
-                Bubbler.build(bubble: cell.rightView, with: item)
-                cell.canReply = false
-                cell.performReply = performReply
-                return cell
-            }
-        )
-    }
+  static func incomingText(
+    performReply: @escaping () -> Void,
+    showRound: @escaping (String?) -> Void
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        item.status == .received
+        && item.replyMessageId == nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: IncomingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.build(bubble: cell.leftView, with: item)
+        cell.canReply = item.status == .received
+        cell.performReply = performReply
+        cell.leftView.didTapShowRound = { showRound(item.roundURL) }
+        cell.leftView.revertBottomStackOrder()
+        return cell
+      }
+    )
+  }
+  
+  static func outgoingText(
+    performReply: @escaping () -> Void,
+    showRound: @escaping (String?) -> Void
+  ) -> Self {
+    .init(
+      canBuild: { item in
+        (item.status == .sending || item.status == .sent)
+        && item.replyMessageId == nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: OutgoingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.build(bubble: cell.rightView, with: item)
+        cell.canReply = item.status == .sent
+        cell.performReply = performReply
+        cell.rightView.didTapShowRound = { showRound(item.roundURL) }
+        
+        return cell
+      }
+    )
+  }
+  
+  static func outgoingFailedText(performReply: @escaping () -> Void) -> Self {
+    .init(
+      canBuild: { item in
+        (item.status == .sendingFailed || item.status == .sendingTimedOut)
+        && item.replyMessageId == nil
+        
+      }, build: { item, collectionView, indexPath in
+        let cell: OutgoingFailedTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+        
+        Bubbler.build(bubble: cell.rightView, with: item)
+        cell.canReply = false
+        cell.performReply = performReply
+        return cell
+      }
+    )
+  }
 }
 
 struct ActionFactory {
-    enum Action {
-        case copy
-        case retry
-        case reply
-        case delete
-        case report
-
-        var title: String {
-            switch self {
-
-            case .copy:
-                return Localized.Chat.BubbleMenu.copy
-            case .retry:
-                return Localized.Chat.BubbleMenu.retry
-            case .reply:
-                return Localized.Chat.BubbleMenu.reply
-            case .delete:
-                return Localized.Chat.BubbleMenu.delete
-            case .report:
-                return Localized.Chat.BubbleMenu.report
-            }
-        }
+  enum Action {
+    case copy
+    case retry
+    case reply
+    case delete
+    case report
+    
+    var title: String {
+      switch self {
+        
+      case .copy:
+        return Localized.Chat.BubbleMenu.copy
+      case .retry:
+        return Localized.Chat.BubbleMenu.retry
+      case .reply:
+        return Localized.Chat.BubbleMenu.reply
+      case .delete:
+        return Localized.Chat.BubbleMenu.delete
+      case .report:
+        return Localized.Chat.BubbleMenu.report
+      }
     }
-
-    static func build(
-        from item: Message,
-        action: Action,
-        closure: @escaping (Message) -> Void
-    ) -> UIAction? {
-
-        switch action {
-        case .report:
-            guard item.status == .received else { return nil }
-        case .reply:
-            guard item.status == .received || item.status == .sent else { return nil }
-        case .retry:
-            guard item.status == .sendingFailed || item.status == .sendingTimedOut else { return nil }
-        case .delete, .copy:
-            break
-        }
-
-        return UIAction(
-            title: action.title,
-            state: .off,
-            handler: { _ in closure(item) }
-        )
+  }
+  
+  static func build(
+    from item: Message,
+    action: Action,
+    closure: @escaping (Message) -> Void
+  ) -> UIAction? {
+    
+    switch action {
+    case .report:
+      guard item.status == .received else { return nil }
+    case .reply:
+      guard item.status == .received || item.status == .sent else { return nil }
+    case .retry:
+      guard item.status == .sendingFailed || item.status == .sendingTimedOut else { return nil }
+    case .delete, .copy:
+      break
     }
+    
+    return UIAction(
+      title: action.title,
+      state: .off,
+      handler: { _ in closure(item) }
+    )
+  }
 }
diff --git a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
index aa2481e2d7fef99b50edf6989bc9cc3898218ef6..2456b811a8af7c96ced78c76b14f1e88e4a606bc 100644
--- a/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/GroupChatViewModel.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import XXModels
 import Defaults
 import Foundation
+import AppResources
 import DifferenceKit
 import ReportingFeature
-import DI
 import XXMessengerClient
+import ComposableArchitecture
 
 import struct XXModels.Message
 import XXClient
@@ -18,13 +20,13 @@ enum GroupChatNavigationRoutes: Equatable {
 }
 
 final class GroupChatViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var sendReport: SendReport
-  @Dependency var groupManager: GroupChat
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var toastController: ToastController
+  @Dependency(\.sendReport) var sendReport
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.groupManager) var groupManager
+  @Dependency(\.app.hudManager) var hudManager
+  @Dependency(\.app.toastManager) var toastManager
+  @Dependency(\.reportingStatus) var reportingStatus
 
   @KeyObject(.username, defaultValue: nil) var username: String?
 
@@ -52,7 +54,7 @@ final class GroupChatViewModel {
   private let routesSubject = PassthroughSubject<GroupChatNavigationRoutes, Never>()
 
   var messages: AnyPublisher<[ArraySection<ChatSection, Message>], Never> {
-    database.fetchMessagesPublisher(.init(chat: .group(info.group.id)))
+    try! dbManager.getDB().fetchMessagesPublisher(.init(chat: .group(info.group.id)))
       .replaceError(with: [])
       .map { messages -> [ArraySection<ChatSection, Message>] in
         let groupedByDate = Dictionary(grouping: messages) { domainModel -> Date in
@@ -78,153 +80,90 @@ final class GroupChatViewModel {
   func readAll() {
     let assignment = Message.Assignments(isUnread: false)
     let query = Message.Query(chat: .group(info.group.id))
-    _ = try? database.bulkUpdateMessages(query, assignment)
+    _ = try? dbManager.getDB().bulkUpdateMessages(query, assignment)
   }
 
   func didRequestDelete(_ messages: [Message]) {
-    _ = try? database.deleteMessages(.init(id: Set(messages.map(\.id))))
+    _ = try? dbManager.getDB().deleteMessages(.init(id: Set(messages.map(\.id))))
   }
 
   func didRequestReport(_ message: Message) {
-    if let contact = try? database.fetchContacts(.init(id: [message.senderId])).first {
+    if let contact = try? dbManager.getDB().fetchContacts(.init(id: [message.senderId])).first {
       reportPopupSubject.send(contact)
     }
   }
 
   func send(_ text: String) {
-    var message = Message(
-      senderId: myId,
-      recipientId: nil,
-      groupId: info.group.id,
-      date: Date(),
-      status: .sending,
-      isUnread: false,
-      text: text.trimmingCharacters(in: .whitespacesAndNewlines),
-      replyMessageId: stagedReply?.messageId
-    )
-
-    print("")
-    print("Outgoing GroupMessage:")
-    print("- groupId: \(info.group.id.base64EncodedString().prefix(10))...")
-    print("- senderId: \(myId.base64EncodedString().prefix(10))...")
-    print("- payload.text: \(message.text)")
-
     do {
-      message = try database.saveMessage(message)
-
-      let payload = Payload(
-        text: text.trimmingCharacters(in: .whitespacesAndNewlines),
-        reply: stagedReply
-      ).asData()
-
-      let report = try groupManager.send(
+      var message = Message(
+        senderId: try messenger.e2e.get()!.getContact().getId(),
+        recipientId: nil,
         groupId: info.group.id,
-        message: payload
+        date: Date(),
+        status: .sending,
+        isUnread: false,
+        text: text.trimmingCharacters(in: .whitespacesAndNewlines),
+        replyMessageId: stagedReply?.messageId
       )
-
-      print("- messageId: \(report.messageId.base64EncodedString().prefix(10))...")
-
-      if let foo = stagedReply {
-        print("- payload.reply.messageId: \(foo.messageId.base64EncodedString().prefix(10))...")
-        print("- payload.reply.senderId: \(foo.senderId.base64EncodedString().prefix(10))...")
-      } else {
-        print("- payload.reply: ∅")
-      }
-
-      message.networkId = report.messageId
-
-      try messenger.cMix.get()!.waitForRoundResult(
-        roundList: try report.encode(),
+      message = try dbManager.getDB().saveMessage(message)
+      let report = try groupManager.get()?.send(
+        groupId: info.id,
+        message: MessagePayload(
+          text: text.trimmingCharacters(in: .whitespacesAndNewlines),
+          replyingTo: stagedReply?.messageId
+        ).encode()
+      )
+      message.networkId = report!.messageId
+      message.date = Date.fromTimestamp(Int(report!.timestamp))
+      message = try dbManager.getDB().saveMessage(message)
+      try messenger.cMix.get()?.waitForRoundResult(
+        roundList: try report!.encode(),
         timeoutMS: 15_000,
-        callback: .init(handle: {
-          switch $0 {
+        callback: .init(handle: { result in
+          switch result {
           case .delivered:
             message.status = .sent
-            if let foo = try? self.database.saveMessage(message) {
-              message = foo
-            }
           case .notDelivered(timedOut: let timedOut):
-            if timedOut {
-              message.status = .sendingTimedOut
-            } else {
-              message.status = .sendingFailed
-            }
-
-            if let foo = try? self.database.saveMessage(message) {
-              message = foo
-            }
+            message.status = timedOut ? .sendingTimedOut : .sendingFailed
           }
+          _ = try? self.dbManager.getDB().saveMessage(message)
         })
       )
-
-      print("")
-
-      message.roundURL = report.roundURL
-      message.date = Date.fromTimestamp(Int(report.timestamp))
-      message = try database.saveMessage(message)
     } catch {
-      message.status = .sendingFailed
-      if let foo = try? database.saveMessage(message) {
-        message = foo
-      }
+      print(error.localizedDescription)
     }
-
-    stagedReply = nil
   }
 
   func retry(_ message: Message) {
-    var message = message
-
     do {
+      var message = message
       message.status = .sending
-      message = try database.saveMessage(message)
-
-      var reply: Reply?
-
-      if let replyId = message.replyMessageId {
-        reply = Reply(messageId: replyId, senderId: myId)
-      }
-
-      let report = try groupManager.send(
-        groupId: message.groupId!,
-        message: Payload(
-          text: message.text,
-          reply: reply
-        ).asData()
+      message = try dbManager.getDB().saveMessage(message)
+      let report = try groupManager.get()?.send(
+        groupId: info.id,
+        message: MessagePayload(
+          text: message.text.trimmingCharacters(in: .whitespacesAndNewlines),
+          replyingTo: stagedReply?.messageId
+        ).encode()
       )
-
-      try messenger.cMix.get()!.waitForRoundResult(
-        roundList: try report.encode(),
+      message.networkId = report!.messageId
+      message.date = Date.fromTimestamp(Int(report!.timestamp))
+      message = try dbManager.getDB().saveMessage(message)
+      try messenger.cMix.get()?.waitForRoundResult(
+        roundList: try report!.encode(),
         timeoutMS: 15_000,
-        callback: .init(handle: {
-          switch $0 {
+        callback: .init(handle: { result in
+          switch result {
           case .delivered:
             message.status = .sent
-            if let foo = try? self.database.saveMessage(message) {
-              message = foo
-            }
           case .notDelivered(timedOut: let timedOut):
-            if timedOut {
-              message.status = .sendingTimedOut
-            } else {
-              message.status = .sendingFailed
-            }
-
-            if let foo = try? self.database.saveMessage(message) {
-              message = foo
-            }
+            message.status = timedOut ? .sendingTimedOut : .sendingFailed
           }
+          _ = try? self.dbManager.getDB().saveMessage(message)
         })
       )
-
-      message.networkId = report.messageId
-      message.date = Date.fromTimestamp(Int(report.timestamp))
-      message = try database.saveMessage(message)
     } catch {
-      message.status = .sendingFailed
-      if let foo = try? database.saveMessage(message) {
-        message = foo
-      }
+      print(error.localizedDescription)
     }
   }
 
@@ -241,7 +180,7 @@ final class GroupChatViewModel {
   }
 
   func getReplyContent(for messageId: Data) -> (String, String) {
-    guard let message = try? database.fetchMessages(.init(networkId: messageId)).first else {
+    guard let message = try? dbManager.getDB().fetchMessages(.init(networkId: messageId)).first else {
       return ("[DELETED]", "[DELETED]")
     }
 
@@ -251,7 +190,7 @@ final class GroupChatViewModel {
   func getName(from senderId: Data) -> String {
     guard senderId != myId else { return "You" }
 
-    guard let contact = try? database.fetchContacts(.init(id: [senderId])).first else {
+    guard let contact = try? dbManager.getDB().fetchContacts(.init(id: [senderId])).first else {
       return "[DELETED]"
     }
 
@@ -290,18 +229,18 @@ final class GroupChatViewModel {
       }
     )
 
-    hudController.show()
+    hudManager.show()
     sendReport(report) { result in
       switch result {
       case .failure(let error):
         DispatchQueue.main.async {
-          self.hudController.show(.init(error: error))
+          self.hudManager.show(.init(error: error))
         }
 
       case .success(_):
         self.blockContact(contact)
         DispatchQueue.main.async {
-          self.hudController.dismiss()
+          self.hudManager.hide()
           self.presentReportConfirmation(contact: contact)
           completion()
         }
@@ -312,12 +251,12 @@ final class GroupChatViewModel {
   private func blockContact(_ contact: XXModels.Contact) {
     var contact = contact
     contact.isBlocked = true
-    _ = try? database.saveContact(contact)
+    _ = try? dbManager.getDB().saveContact(contact)
   }
 
   private func presentReportConfirmation(contact: XXModels.Contact) {
     let name = (contact.nickname ?? contact.username) ?? "the contact"
-    toastController.enqueueToast(model: .init(
+    toastManager.enqueue(.init(
       title: "Your report has been sent and \(name) is now blocked.",
       leftImage: Asset.requestSentToaster.image
     ))
diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
index adc8743e058ea95d384a5a60bb522f2312f139c2..92b93761bcf599f72275369d966ee39e05ef22f7 100644
--- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
@@ -1,17 +1,17 @@
-import DI
 import UIKit
 import Shared
+import AppCore
 import Combine
-import XXLogger
 import XXModels
 import XXClient
 import Defaults
-import Navigation
-import Foundation
-import Permissions
+import AppResources
+import Dependencies
+import AppNavigation
 import DifferenceKit
 import ReportingFeature
 import XXMessengerClient
+import PermissionsFeature
 
 import struct XXModels.Message
 import struct XXModels.FileTransfer
@@ -28,16 +28,16 @@ enum SingleChatNavigationRoutes: Equatable {
 }
 
 final class SingleChatViewModel: NSObject {
-  @Dependency var logger: XXLogger
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var sendReport: SendReport
-  @Dependency var hudController: HUDController
-  @Dependency var permissions: PermissionHandling
-  @Dependency var toastController: ToastController
-  @Dependency var networkMonitor: NetworkMonitoring
-  @Dependency var transferManager: XXClient.FileTransfer
-  
+  @Dependency(\.sendReport) var sendReport
+  @Dependency(\.permissions) var permissions
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.sendImage) var sendImage
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.app.hudManager) var hudManager
+  @Dependency(\.app.sendMessage) var sendMessage
+  @Dependency(\.app.toastManager) var toastManager
+  @Dependency(\.app.networkMonitor) var networkMonitor
+
   @KeyObject(.username, defaultValue: nil) var username: String?
   
   var contact: XXModels.Contact { contactSubject.value }
@@ -53,12 +53,11 @@ final class SingleChatViewModel: NSObject {
   
   var isOnline: AnyPublisher<Bool, Never> {
     networkMonitor
-      .statusPublisher
+      .observeStatus()
       .map { $0 == .available }
       .eraseToAnyPublisher()
   }
-  
-  
+
   var myId: Data {
     try! messenger.e2e.get()!.getContact().getId()
   }
@@ -84,7 +83,7 @@ final class SingleChatViewModel: NSObject {
     if contact.isRecent == true {
       var contact = contact
       contact.isRecent = false
-      _ = try? database.saveContact(contact)
+      _ = try? dbManager.getDB().saveContact(contact)
     }
   }
   
@@ -98,13 +97,13 @@ final class SingleChatViewModel: NSObject {
     
     updateRecentState(contact)
     
-    database.fetchContactsPublisher(Contact.Query(id: [contact.id]))
+    try! dbManager.getDB().fetchContactsPublisher(Contact.Query(id: [contact.id]))
       .replaceError(with: [])
       .compactMap { $0.first }
       .sink { [unowned self] in contactSubject.send($0) }
       .store(in: &cancellables)
     
-    database.fetchMessagesPublisher(.init(chat: .direct(myId, contact.id)))
+    try! dbManager.getDB().fetchMessagesPublisher(.init(chat: .direct(myId, contact.id)))
       .replaceError(with: [])
       .map {
         let groupedByDate = Dictionary(grouping: $0) { domainModel -> Date in
@@ -125,296 +124,102 @@ final class SingleChatViewModel: NSObject {
     }))
   }
   
-  // MARK: Public
-  
   func getFileTransferWith(id: Data) -> FileTransfer {
-    guard let transfer = try? database.fetchFileTransfers(.init(id: [id])).first else {
+    guard let transfer = try? dbManager.getDB().fetchFileTransfers(.init(id: [id])).first else {
       fatalError()
     }
     
     return transfer
   }
   
-  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 {
-//
-//    }
-  }
+  func didSendAudio(url: URL) {}
   
   func didSend(image: UIImage) {
     guard let imageData = image.orientedUp().jpegData(compressionQuality: 1.0) else { return }
-    hudController.show()
-    
-    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)
-      
-      hudController.dismiss()
-    } catch {
-      hudController.show(.init(error: error))
+
+    sendImage(imageData, to: contact.id, onError: {
+      print("\($0.localizedDescription)")
+    }) {
+      print("finished")
     }
   }
-  
+
   func readAll() {
     let assignment = Message.Assignments(isUnread: false)
     let query = Message.Query(chat: .direct(myId, contact.id))
-    _ = try? database.bulkUpdateMessages(query, assignment)
+    _ = try? dbManager.getDB().bulkUpdateMessages(query, assignment)
   }
-  
+
   func didRequestDeleteAll() {
-    _ = try? database.deleteMessages(.init(chat: .direct(myId, contact.id)))
+    _ = try? dbManager.getDB().deleteMessages(.init(chat: .direct(myId, contact.id)))
   }
-  
+
   func didRequestRetry(_ message: Message) {
-    var message = message
-    
-    do {
-      message.status = .sending
-      message = try database.saveMessage(message)
-      
-      var reply: Reply?
-      
-      if let replyId = message.replyMessageId {
-        reply = Reply(messageId: replyId, senderId: myId)
-      }
-      
-      let report = try messenger.e2e.get()!.send(
-        messageType: 2,
-        recipientId: contact.id,
-        payload: Payload(
-          text: message.text,
-          reply: reply
-        ).asData(),
-        e2eParams: GetE2EParams.liveDefault()
-      )
-      
-      try messenger.cMix.get()!.waitForRoundResult(
-        roundList: try report.encode(),
-        timeoutMS: 15_000,
-        callback: .init(handle: {
-          switch $0 {
-          case .delivered:
-            message.status = .sent
-            _ = try? self.database.saveMessage(message)
-            
-          case .notDelivered(timedOut: let timedOut):
-            if timedOut {
-              message.status = .sendingTimedOut
-            } else {
-              message.status = .sendingFailed
-            }
-            
-            _ = try? self.database.saveMessage(message)
-          }
-        })
-      )
-      
-      message.roundURL = report.roundURL
-      message.networkId = report.messageId
-      if let timestamp = report.timestamp {
-        message.date = Date.fromTimestamp(Int(timestamp))
-      }
-      
-      message = try database.saveMessage(message)
-    } catch {
-      print(error.localizedDescription)
-      message.status = .sendingFailed
-      _ = try? database.saveMessage(message)
-    }
+    // TODO
   }
-  
+
   func didNavigateSomewhere() {
     navigationRoutes.send(.none)
   }
-  
+
   @discardableResult
   func didTest(permission: PermissionType) -> Bool {
     switch permission {
     case .camera:
-      if permissions.isCameraAllowed {
+      if permissions.camera.status() {
         navigationRoutes.send(.camera)
       } else {
         navigationRoutes.send(.cameraPermission)
       }
     case .library:
-      if permissions.isPhotosAllowed {
+      if permissions.library.status() {
         navigationRoutes.send(.library)
       } else {
         navigationRoutes.send(.libraryPermission)
       }
     case .microphone:
-      if permissions.isMicrophoneAllowed {
+      if permissions.microphone.status() {
         return true
       } else {
         navigationRoutes.send(.microphonePermission)
       }
     }
-    
+
     return false
   }
-  
+
   func didRequestCopy(_ model: Message) {
     UIPasteboard.general.string = model.text
   }
-  
+
   func didRequestDeleteSingle(_ model: Message) {
     didRequestDelete([model])
   }
-  
+
   func didRequestReport(_: Message) {
     reportPopupSubject.send()
   }
-  
+
   func abortReply() {
     stagedReply = nil
   }
-  
+
   func send(_ string: String) {
-    var message: Message = .init(
-      senderId: myId,
-      recipientId: contact.id,
-      groupId: nil,
-      date: Date(),
-      status: .sending,
-      isUnread: false,
+    sendMessage(
       text: string.trimmingCharacters(in: .whitespacesAndNewlines),
-      replyMessageId: stagedReply?.messageId
-    )
-    
-    DispatchQueue.global().async { [weak self] in
-      guard let self else { return }
-      
-      do {
-        message = try self.database.saveMessage(message)
-        
-        let report = try self.messenger.e2e.get()!.send(
-          messageType: 2,
-          recipientId: self.contact.id,
-          payload: Payload(text: message.text, reply: self.stagedReply).asData(),
-          e2eParams: GetE2EParams.liveDefault()
-        )
-        
-        try self.messenger.cMix.get()!.waitForRoundResult(
-          roundList: try report.encode(),
-          timeoutMS: 15_000,
-          callback: .init(handle: {
-            switch $0 {
-            case .delivered:
-              message.status = .sent
-              _ = try? self.database.saveMessage(message)
-              
-            case .notDelivered(timedOut: let timedOut):
-              if timedOut {
-                message.status = .sendingTimedOut
-              } else {
-                message.status = .sendingFailed
-              }
-              
-              _ = try? self.database.saveMessage(message)
-            }
-          })
-        )
-        
-        message.roundURL = report.roundURL
-        message.networkId = report.messageId
-        if let timestamp = report.timestamp {
-          message.date = Date.fromTimestamp(Int(timestamp))
-        }
-        
-        message = try self.database.saveMessage(message)
-      } catch {
-        print(error.localizedDescription)
-        message.status = .sendingFailed
-        _ = try? self.database.saveMessage(message)
+      replyingTo: stagedReply?.messageId,
+      to: contact.id,
+      onError: {
+        print("\($0.localizedDescription)")
+      }, completion: {
+        print("completed")
       }
-      
-      self.stagedReply = nil
-    }
+    )
   }
-  
+
   func didRequestReply(_ message: Message) {
     guard let networkId = message.networkId else { return }
-    
+
     let senderTitle: String = {
       if message.senderId == myId {
         return "You"
@@ -422,24 +227,24 @@ final class SingleChatViewModel: NSObject {
         return (contact.nickname ?? contact.username) ?? "Fetching username..."
       }
     }()
-    
+
     replySubject.send((senderTitle, message.text))
     stagedReply = Reply(messageId: networkId, senderId: message.senderId)
   }
-  
+
   func getReplyContent(for messageId: Data) -> (String, String) {
-    guard let message = try? database.fetchMessages(.init(networkId: messageId)).first else {
+    guard let message = try? dbManager.getDB().fetchMessages(.init(networkId: messageId)).first else {
       return ("[DELETED]", "[DELETED]")
     }
-    
-    guard let contact = try? database.fetchContacts(.init(id: [message.senderId])).first else {
+
+    guard let contact = try? dbManager.getDB().fetchContacts(.init(id: [message.senderId])).first else {
       fatalError()
     }
-    
+
     let contactTitle = (contact.nickname ?? contact.username) ?? "You"
     return (contactTitle, message.text)
   }
-  
+
   func showRoundFrom(_ roundURL: String?) {
     if let urlString = roundURL, !urlString.isEmpty {
       navigationRoutes.send(.webview(urlString))
@@ -447,26 +252,26 @@ final class SingleChatViewModel: NSObject {
       navigationRoutes.send(.waitingRound)
     }
   }
-  
+
   func didRequestDelete(_ items: [Message]) {
-    _ = try? database.deleteMessages(.init(id: Set(items.compactMap(\.id))))
+    _ = try? dbManager.getDB().deleteMessages(.init(id: Set(items.compactMap(\.id))))
   }
-  
+
   func itemWith(id: Int64) -> Message? {
     sectionsRelay.value.flatMap(\.elements).first(where: { $0.id == id })
   }
-  
+
   func itemAt(indexPath: IndexPath) -> Message? {
     guard sectionsRelay.value.count > indexPath.section else { return nil }
-    
+
     let items = sectionsRelay.value[indexPath.section].elements
     return items.count > indexPath.row ? items[indexPath.row] : nil
   }
-  
+
   func section(at index: Int) -> ChatSection? {
     sectionsRelay.value.count > 0 ? sectionsRelay.value[index].model : nil
   }
-  
+
   func report(screenshot: UIImage, completion: @escaping (Bool) -> Void) {
     let report = Report(
       sender: .init(
@@ -480,36 +285,36 @@ final class SingleChatViewModel: NSObject {
       type: .dm,
       screenshot: screenshot.pngData()!
     )
-    
-    hudController.show()
+
+    hudManager.show()
     sendReport(report) { result in
       switch result {
       case .failure(let error):
         DispatchQueue.main.async {
-          self.hudController.show(.init(error: error))
+          self.hudManager.show(.init(error: error))
           completion(false)
         }
-        
+
       case .success(_):
         self.blockContact()
         DispatchQueue.main.async {
-          self.hudController.dismiss()
+          self.hudManager.hide()
           self.presentReportConfirmation()
           completion(true)
         }
       }
     }
   }
-  
+
   private func blockContact() {
     var contact = contact
     contact.isBlocked = true
-    _ = try? database.saveContact(contact)
+    _ = try? dbManager.getDB().saveContact(contact)
   }
-  
+
   private func presentReportConfirmation() {
     let name = (contact.nickname ?? contact.username) ?? "the contact"
-    toastController.enqueueToast(model: .init(
+    toastManager.enqueue(.init(
       title: "Your report has been sent and \(name) is now blocked.",
       leftImage: Asset.requestSentToaster.image
     ))
diff --git a/Sources/ChatFeature/Views/Cells/AudioMessageView.swift b/Sources/ChatFeature/Views/Cells/AudioMessageView.swift
index 5982ffc49253c7d5b7a21939290b11f0f48e2f20..88b866abe701f4d3af9aa4041616dc1fa1a02d34 100644
--- a/Sources/ChatFeature/Views/Cells/AudioMessageView.swift
+++ b/Sources/ChatFeature/Views/Cells/AudioMessageView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 typealias OutgoingAudioCell = CollectionCell<FlexibleSpace, AudioMessageView>
 typealias IncomingAudioCell = CollectionCell<AudioMessageView, FlexibleSpace>
diff --git a/Sources/ChatFeature/Views/Cells/AudioView.swift b/Sources/ChatFeature/Views/Cells/AudioView.swift
index 2a46a7a0309bf1f4a184e3d0cbfe88023f7f653d..e3d26bcbd683907b94073cfbea6aa0250e2ec0ef 100644
--- a/Sources/ChatFeature/Views/Cells/AudioView.swift
+++ b/Sources/ChatFeature/Views/Cells/AudioView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class AudioView: UIView {
     // MARK: UI
diff --git a/Sources/ChatFeature/Views/Cells/DocumentMessageView.swift b/Sources/ChatFeature/Views/Cells/DocumentMessageView.swift
index 2a8cf025f16d524858da87af728cbdd7bcbf1de7..8556277cc8bbe73aabf5511be4fb59333f9d2509 100644
--- a/Sources/ChatFeature/Views/Cells/DocumentMessageView.swift
+++ b/Sources/ChatFeature/Views/Cells/DocumentMessageView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 typealias OutgoingDocumentCell = CollectionCell<FlexibleSpace, DocumentMessageView>
 typealias IncomingDocumentCell = CollectionCell<DocumentMessageView, FlexibleSpace>
diff --git a/Sources/ChatFeature/Views/Cells/ImageMessageView.swift b/Sources/ChatFeature/Views/Cells/ImageMessageView.swift
index 88efa910ce3ef46a3b1f8012382b1287117b477d..92cfc9f3151cd14dccee4f52aa9bd3f14cebcf81 100644
--- a/Sources/ChatFeature/Views/Cells/ImageMessageView.swift
+++ b/Sources/ChatFeature/Views/Cells/ImageMessageView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 typealias OutgoingImageCell = CollectionCell<FlexibleSpace, ImageMessageView>
 typealias IncomingImageCell = CollectionCell<ImageMessageView, FlexibleSpace>
diff --git a/Sources/ChatFeature/Views/Cells/ReplyStackMessageView.swift b/Sources/ChatFeature/Views/Cells/ReplyStackMessageView.swift
index 20a74276710b492a845ad7b276fc79665a6a1baf..73e063e850229f3ba0f62f6105d6851a6ea4c55c 100644
--- a/Sources/ChatFeature/Views/Cells/ReplyStackMessageView.swift
+++ b/Sources/ChatFeature/Views/Cells/ReplyStackMessageView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 typealias IncomingReplyCell = CollectionCell<ReplyStackMessageView, FlexibleSpace>
 typealias OutgoingReplyCell = CollectionCell<FlexibleSpace, ReplyStackMessageView>
diff --git a/Sources/ChatFeature/Views/Cells/ReplyView.swift b/Sources/ChatFeature/Views/Cells/ReplyView.swift
index e64def34d02055d356efefd14ce5b6a4e5cab05e..3f8e1f8dcac7bfd7edcc07e62b464d27b4000370 100644
--- a/Sources/ChatFeature/Views/Cells/ReplyView.swift
+++ b/Sources/ChatFeature/Views/Cells/ReplyView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ReplyView: UIView {
     let space = UIView()
diff --git a/Sources/ChatFeature/Views/Cells/StackMessageView.swift b/Sources/ChatFeature/Views/Cells/StackMessageView.swift
index 2c5a3c9f3f6c9e86735c28eb4edb64efcfd5d44f..df89a30363624c426e6119942907437a7ad9ef79 100644
--- a/Sources/ChatFeature/Views/Cells/StackMessageView.swift
+++ b/Sources/ChatFeature/Views/Cells/StackMessageView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 typealias IncomingTextCell = CollectionCell<StackMessageView, FlexibleSpace>
 typealias OutgoingTextCell = CollectionCell<FlexibleSpace, StackMessageView>
diff --git a/Sources/ChatFeature/Views/ChatMenuView.swift b/Sources/ChatFeature/Views/ChatMenuView.swift
index 6b6f06bfe6ad54326de469f45b50ecf928aa2a3c..5ed237dd36f3d3f616337e88ab34f8ca81b2a805 100644
--- a/Sources/ChatFeature/Views/ChatMenuView.swift
+++ b/Sources/ChatFeature/Views/ChatMenuView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class ChatMenuView: UIToolbar {
     enum Action {
diff --git a/Sources/ChatFeature/Views/ChatView.swift b/Sources/ChatFeature/Views/ChatView.swift
index 0d3529709d1b646a43c3d3fa5b41cdf05d016821..34026c0cc6aa77955b0363a12e1f5bc5f6ffa244 100644
--- a/Sources/ChatFeature/Views/ChatView.swift
+++ b/Sources/ChatFeature/Views/ChatView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatView: UIView {
     let titleLabel = UILabel()
diff --git a/Sources/ChatFeature/Views/GroupHeaderView.swift b/Sources/ChatFeature/Views/GroupHeaderView.swift
index b33415707304f070f172764a5ee8a49d89a1a10d..fdd4940153806a413e0362ac55d11afde886e31e 100644
--- a/Sources/ChatFeature/Views/GroupHeaderView.swift
+++ b/Sources/ChatFeature/Views/GroupHeaderView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 struct Member {
     let title: String
diff --git a/Sources/ChatFeature/Views/RetrySheetView.swift b/Sources/ChatFeature/Views/RetrySheetView.swift
index 44c1de62c74e6ab1f19eacb18a9fd22ff02166f1..1b79665bf9acf383edfa3fc7dfa5239447c9b962 100644
--- a/Sources/ChatFeature/Views/RetrySheetView.swift
+++ b/Sources/ChatFeature/Views/RetrySheetView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RetrySheetView: UIView {
     // MARK: UI
diff --git a/Sources/ChatFeature/Views/SectionHeaderView.swift b/Sources/ChatFeature/Views/SectionHeaderView.swift
index 564ad98d840772945e8dfcda3a8921d81b23f4cd..9e78f977d123f628f72300350953dcad2aa9f1d0 100644
--- a/Sources/ChatFeature/Views/SectionHeaderView.swift
+++ b/Sources/ChatFeature/Views/SectionHeaderView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SectionHeaderView: UICollectionReusableView {
     // MARK: UI
diff --git a/Sources/ChatFeature/Views/SheetButton.swift b/Sources/ChatFeature/Views/SheetButton.swift
index c20ec8931d7b7b303dc35c819f3b6ad7ba09394c..f24e8a06a62e1689957c6e570d08a19d5787faf3 100644
--- a/Sources/ChatFeature/Views/SheetButton.swift
+++ b/Sources/ChatFeature/Views/SheetButton.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SheetButton: UIControl {
     enum Style {
diff --git a/Sources/ChatFeature/Views/SheetView.swift b/Sources/ChatFeature/Views/SheetView.swift
index a4cdfeb1348a6cd8b369115d6c34272df7649d87..6e305a6f5b1ee5ce1b47b1b1d1c58fa46fc359b4 100644
--- a/Sources/ChatFeature/Views/SheetView.swift
+++ b/Sources/ChatFeature/Views/SheetView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SheetView: UIView {
     let stackView = UIStackView()
diff --git a/Sources/ChatFeature/Views/TextView.swift b/Sources/ChatFeature/Views/TextView.swift
index 1fbc36974b706d916aa6be5b7ce358b322a1cad5..ea7b30e3cfc95e45f677bbf750d8d27eb8c2c275 100644
--- a/Sources/ChatFeature/Views/TextView.swift
+++ b/Sources/ChatFeature/Views/TextView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 /// UITextView avoiding selection
 
diff --git a/Sources/ChatInputFeature/ChatInputView.swift b/Sources/ChatInputFeature/ChatInputView.swift
index eef904e58e8f57277a57a3789bd3db15f7ac7adc..ba81355868eb9ec1347d9b58f21a3e3edf1a7e88 100644
--- a/Sources/ChatInputFeature/ChatInputView.swift
+++ b/Sources/ChatInputFeature/ChatInputView.swift
@@ -2,7 +2,6 @@ import UIKit
 import Shared
 import Combine
 import CasePaths
-import Voxophone
 import AppResources
 import ComposableArchitecture
 
diff --git a/Sources/ChatListFeature/Controller/ChatListController.swift b/Sources/ChatListFeature/Controller/ChatListController.swift
index c141c1ae99af73758f9acb538e98b4e4d7ae94f2..8ad43f6efa8fea9ea98d3894f6726d9d7b75bbe4 100644
--- a/Sources/ChatListFeature/Controller/ChatListController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListController.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
 import Combine
+import AppCore
 import XXModels
-import Navigation
-import DI
+import AppResources
+import Dependencies
+import AppNavigation
 
 public final class ChatListController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
   
   private lazy var screenView = ChatListView()
   private lazy var topLeftView = ChatListTopLeftNavView()
@@ -47,7 +49,7 @@ public final class ChatListController: UIViewController {
   
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
   }
   
@@ -69,9 +71,15 @@ public final class ChatListController: UIViewController {
       .sink { [unowned self] in
         switch $0 {
         case .didTapSearch:
-          navigator.perform(PresentSearch(searching: nil, replacing: false, on: navigationController!))
+          navigator.perform(PresentSearch(
+            searching: nil,
+            replacing: false,
+            on: navigationController!
+          ))
         case .didTapNewGroup:
-          navigator.perform(PresentNewGroup(on: navigationController!))
+          navigator.perform(
+            PresentGroupDraft(on: navigationController!)
+          )
         }
       }.store(in: &cancellables)
     
diff --git a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
index b9a877cbf6f4942ba12d547a1fdef94aa8cf502d..284a571745afde1d577fa0a34afe48be13fd3d76 100644
--- a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
@@ -1,8 +1,9 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
-import DI
+import AppResources
+import Dependencies
+import AppNavigation
 
 class ChatSearchListTableViewDiffableDataSource: UITableViewDiffableDataSource<SearchSection, SearchItem> {
   override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
@@ -16,7 +17,7 @@ class ChatSearchListTableViewDiffableDataSource: UITableViewDiffableDataSource<S
 }
 
 final class ChatSearchTableController: UITableViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private let viewModel: ChatListViewModel
   private let cellHeight: CGFloat = 83.0
diff --git a/Sources/ChatListFeature/Controller/ChatListTableController.swift b/Sources/ChatListFeature/Controller/ChatListTableController.swift
index 8db077fa8c454239b6d1b5553c9c25632ed7e38d..e1c2e06b98954ab0f99d4fa6452fd781a6ede8bd 100644
--- a/Sources/ChatListFeature/Controller/ChatListTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListTableController.swift
@@ -2,17 +2,18 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import Navigation
+import AppNavigation
 import DifferenceKit
 import DrawerFeature
-import DI
+import Dependencies
+import AppResources
 
 extension ChatInfo: Differentiable {
   public var differenceIdentifier: ChatInfo.ID { id }
 }
 
 final class ChatListTableController: UITableViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private var rows = [ChatInfo]()
   private let viewModel: ChatListViewModel
diff --git a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
index 1838460803a0b4e6b2068247db601d4038c6f708..0e4c28520f58202435ff65d4d2c0a9069fd537fd 100644
--- a/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
+++ b/Sources/ChatListFeature/ViewModel/ChatListViewModel.swift
@@ -3,9 +3,10 @@ import Shared
 import Combine
 import XXModels
 import Defaults
+import AppCore
+import Dependencies
 import XXMessengerClient
 import ReportingFeature
-import DI
 
 import struct XXModels.Group
 import XXClient
@@ -24,11 +25,11 @@ typealias RecentsSnapshot = NSDiffableDataSourceSnapshot<SectionId, XXModels.Con
 typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>
 
 final class ChatListViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var groupManager: GroupChat
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.groupManager) var groupManager
+  @Dependency(\.app.hudManager) var hudManager
+  @Dependency(\.reportingStatus) var reportingStatus
   
   // TO REFACTOR:
   var isOnline: AnyPublisher<Bool, Never> {
@@ -51,7 +52,7 @@ final class ChatListViewModel {
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
     
-    return database.fetchContactsPublisher(query)
+    return try! dbManager.getDB().fetchContactsPublisher(query)
       .replaceError(with: [])
       .map {
         let section = SectionId()
@@ -69,7 +70,7 @@ final class ChatListViewModel {
     )
     
     return Publishers.CombineLatest3(
-      database.fetchContactsPublisher(contactsQuery)
+      try! dbManager.getDB().fetchContactsPublisher(contactsQuery)
         .replaceError(with: [])
         .map { $0.filter { $0.id != self.myId }},
       chatsPublisher,
@@ -135,8 +136,8 @@ final class ChatListViewModel {
     )
     
     return Publishers.CombineLatest(
-      database.fetchContactsPublisher(contactsQuery).replaceError(with: []),
-      database.fetchGroupsPublisher(groupQuery).replaceError(with: [])
+      try! dbManager.getDB().fetchContactsPublisher(contactsQuery).replaceError(with: []),
+      try! dbManager.getDB().fetchGroupsPublisher(groupQuery).replaceError(with: [])
     )
     .map { $0.0.count + $0.1.count }
     .eraseToAnyPublisher()
@@ -147,7 +148,7 @@ final class ChatListViewModel {
   private let chatsSubject = CurrentValueSubject<[ChatInfo], Never>([])
   
   init() {
-    database.fetchChatInfosPublisher(
+    try! dbManager.getDB().fetchChatInfosPublisher(
       ChatInfo.Query(
         contactChatInfoQuery: .init(
           userId: myId,
@@ -174,25 +175,27 @@ final class ChatListViewModel {
   }
   
   func leave(_ group: Group) {
-    hudController.show()
-    
+    guard let manager = groupManager.get() else {
+      return
+    }
+    hudManager.show()
     do {
-      try groupManager.leaveGroup(groupId: group.id)
-      try database.deleteMessages(.init(chat: .group(group.id)))
-      try database.deleteGroup(group)
-      hudController.dismiss()
+      try manager.leaveGroup(groupId: group.id)
+      try dbManager.getDB().deleteMessages(.init(chat: .group(group.id)))
+      try dbManager.getDB().deleteGroup(group)
+      hudManager.hide()
     } catch {
-      hudController.show(.init(error: error))
+      hudManager.show(.init(error: error))
     }
   }
   
   func clear(_ contact: XXModels.Contact) {
-    _ = try? database.deleteMessages(.init(chat: .direct(myId, contact.id)))
+    _ = try? dbManager.getDB().deleteMessages(.init(chat: .direct(myId, contact.id)))
   }
   
   func groupInfo(from group: Group) -> GroupInfo? {
     let query = GroupInfo.Query(groupId: group.id)
-    guard let info = try? database.fetchGroupInfos(query).first else {
+    guard let info = try? dbManager.getDB().fetchGroupInfos(query).first else {
       return nil
     }
     
diff --git a/Sources/ChatListFeature/Views/ChatListCell.swift b/Sources/ChatListFeature/Views/ChatListCell.swift
index e097c7fc6c3731d78c76fbbab9a58cdfb6548b64..9ee550dad267464a979b43926222b85cfdf467fb 100644
--- a/Sources/ChatListFeature/Views/ChatListCell.swift
+++ b/Sources/ChatListFeature/Views/ChatListCell.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatListCell: UITableViewCell {
   let titleLabel = UILabel()
diff --git a/Sources/ChatListFeature/Views/ChatListContainerView.swift b/Sources/ChatListFeature/Views/ChatListContainerView.swift
index b34fc50bb3690707488c0842058c818b1092de6a..77f35111eecf168a96a51a56996f91bb5e0d23a1 100644
--- a/Sources/ChatListFeature/Views/ChatListContainerView.swift
+++ b/Sources/ChatListFeature/Views/ChatListContainerView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatListContainerView: UIView {
   let separatorView = UIView()
diff --git a/Sources/ChatListFeature/Views/ChatListEmptyView.swift b/Sources/ChatListFeature/Views/ChatListEmptyView.swift
index 449c71451b679c18f6ae8fda508d9678b648773d..4004ad713f9fb2e96c43ba4274b61305ce892108 100644
--- a/Sources/ChatListFeature/Views/ChatListEmptyView.swift
+++ b/Sources/ChatListFeature/Views/ChatListEmptyView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatListEmptyView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/ChatListFeature/Views/ChatListMenuView.swift b/Sources/ChatListFeature/Views/ChatListMenuView.swift
index 4c700f31414cb2a0d107c076c282bafd6380e16c..94c18bdfca28937a535117f9ad18a90c76d06caf 100644
--- a/Sources/ChatListFeature/Views/ChatListMenuView.swift
+++ b/Sources/ChatListFeature/Views/ChatListMenuView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class ChatListMenuView: UIToolbar {
   enum Action {
diff --git a/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift b/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
index 6f452d4e51b3a0a39cee4ded26339cc143fd894a..1174d4019d14daffa80bfc2887962efdb43fde93 100644
--- a/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
+++ b/Sources/ChatListFeature/Views/ChatListRecentContactCell.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatListRecentContactCell: UICollectionViewCell {
   let titleLabel = UILabel()
diff --git a/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift b/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
index 7ed956f4f3736c5c96bebdeaf59f8b7d198bc78f..9e35a63d2cabef7ec6561a174a4e39238e6773ca 100644
--- a/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
+++ b/Sources/ChatListFeature/Views/ChatListTopLeftNavView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class ChatListTopLeftNavView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift b/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
index 182187b997840d7d7d7164f29b5fe4501cabf551..1e7426425483439a8e884c224aa74e59ef30a65a 100644
--- a/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
+++ b/Sources/ChatListFeature/Views/ChatListTopRightNavView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class ChatListTopRightNavView: UIView {
   enum Action {
diff --git a/Sources/ChatListFeature/Views/ChatListView.swift b/Sources/ChatListFeature/Views/ChatListView.swift
index 4bfe400fe287e385551605d1b9c9f343f168f241..9b90b60a55e5db25a5844ac604162080c969e825 100644
--- a/Sources/ChatListFeature/Views/ChatListView.swift
+++ b/Sources/ChatListFeature/Views/ChatListView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatListView: UIView {
   let snackBar = SnackBar()
diff --git a/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift b/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
index ec55193886cf161efbdf1159737ce16281fb334a..7853c79e5eb9e3ad88377e7db9a030f861797b1f 100644
--- a/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
+++ b/Sources/ChatListFeature/Views/ChatSearchEmptyView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatSearchEmptyView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/CheckVersion/CheckVersion.swift b/Sources/CheckVersion/CheckVersion.swift
new file mode 100644
index 0000000000000000000000000000000000000000..32cd955542ab8311ae679007e73aaa29f8c1819f
--- /dev/null
+++ b/Sources/CheckVersion/CheckVersion.swift
@@ -0,0 +1,62 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct CheckVersion {
+  public enum VersionState {
+    case updated
+    case outdated(String)
+    case wayTooOld(String, String)
+  }
+
+  public enum Error: Swift.Error {
+    case noLocalVersion
+    case failureFetchingRemote(FetchRemoteVersion.Error)
+  }
+
+  public typealias Completion = (Result<VersionState, Error>) -> Void
+
+  public var run: (@escaping Completion) -> Void
+
+  public func callAsFunction(_ completion: @escaping Completion) -> Void {
+    run(completion)
+  }
+}
+
+extension CheckVersion {
+  public static func live(
+    local: FetchLocalVersion = .live,
+    remote: FetchRemoteVersion = .live
+  ) -> CheckVersion {
+    .init { completion in
+      remote {
+        switch $0 {
+        case .success(let remoteModel):
+          guard let localVersion = local() else {
+            completion(.failure(.noLocalVersion))
+            return
+          }
+          if localVersion >= remoteModel.details.recommendedVersion {
+            completion(.success(.updated))
+          } else {
+            if localVersion < remoteModel.details.minimumVersion {
+              completion(.success(.wayTooOld(
+                remoteModel.details.appUrl,
+                remoteModel.details.minimumVersionMessage
+              )))
+              return
+            }
+            completion(.success(.outdated(remoteModel.details.appUrl)))
+          }
+        case .failure(let error):
+          completion(.failure(.failureFetchingRemote(error)))
+        }
+      }
+    }
+  }
+}
+
+extension CheckVersion {
+  public static let unimplemented = CheckVersion(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/CheckVersion/Dependency.swift b/Sources/CheckVersion/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..636a64c83d37eb9f639076b1ec80dfd6f2e2a7ed
--- /dev/null
+++ b/Sources/CheckVersion/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum CheckVersionDependencyKey: DependencyKey {
+  static let liveValue: CheckVersion = .live()
+  static let testValue: CheckVersion = .unimplemented
+}
+
+extension DependencyValues {
+  public var checkVersion: CheckVersion {
+    get { self[CheckVersionDependencyKey.self] }
+    set { self[CheckVersionDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/CheckVersion/FetchLocalVersion.swift b/Sources/CheckVersion/FetchLocalVersion.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1954fe744e5a70f30c6d57c121b4218c73dba992
--- /dev/null
+++ b/Sources/CheckVersion/FetchLocalVersion.swift
@@ -0,0 +1,22 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct FetchLocalVersion {
+  public var run: () -> String?
+
+  public func callAsFunction() -> String? {
+    run()
+  }
+}
+
+extension FetchLocalVersion {
+  public static let live = FetchLocalVersion {
+    Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
+  }
+}
+
+extension FetchLocalVersion {
+  public static let unimplemented = FetchLocalVersion(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/CheckVersion/FetchRemoteVersion.swift b/Sources/CheckVersion/FetchRemoteVersion.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e3c19f924df47afb64a01887f6ccae05f63824fa
--- /dev/null
+++ b/Sources/CheckVersion/FetchRemoteVersion.swift
@@ -0,0 +1,51 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct FetchRemoteVersion {
+  public enum Error: Swift.Error {
+    case noData
+    case requestError
+    case decodeFailure
+  }
+
+  public typealias Completion = (Result<Remote, Error>) -> Void
+
+  public var run: (@escaping Completion) -> Void
+
+  public func callAsFunction(_ completion: @escaping Completion) -> Void {
+    run(completion)
+  }
+}
+
+extension FetchRemoteVersion {
+  public static let live = FetchRemoteVersion { completion in
+    let urlString = "https://elixxir-bins.s3-us-west-1.amazonaws.com/client/dapps/appdb.json"
+    let request = URLRequest(
+      url: URL(string: urlString)!,
+      cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
+      timeoutInterval: 5
+    )
+    URLSession.shared.dataTask(with: request) { data, _, error in
+      guard error == nil else {
+        completion(.failure(.requestError))
+        return
+      }
+      guard let data else {
+        completion(.failure(.noData))
+        return
+      }
+      do {
+        let model = try JSONDecoder().decode(Remote.self, from: data)
+        completion(.success(model))
+      } catch {
+        completion(.failure(.decodeFailure))
+      }
+    }.resume()
+  }
+}
+
+extension FetchRemoteVersion {
+  public static let unimplemented = FetchRemoteVersion(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/CheckVersion/RemoteDetailsModel.swift b/Sources/CheckVersion/RemoteDetailsModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d549eb6359ed1c38b4403eae55bf5b45384b77fd
--- /dev/null
+++ b/Sources/CheckVersion/RemoteDetailsModel.swift
@@ -0,0 +1,13 @@
+public struct RemoteDetails: Codable {
+  public var appUrl: String
+  public var minimumVersion: String
+  public var recommendedVersion: String
+  public var minimumVersionMessage: String
+
+  private enum CodingKeys: String, CodingKey {
+    case appUrl = "new_ios_app_url"
+    case minimumVersion = "new_ios_min_version"
+    case minimumVersionMessage = "new_minimum_popup_msg"
+    case recommendedVersion = "new_ios_recommended_version"
+  }
+}
diff --git a/Sources/CheckVersion/RemoteModel.swift b/Sources/CheckVersion/RemoteModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f2a65522f1fe974fb1f31e618c55b6c5956eba7f
--- /dev/null
+++ b/Sources/CheckVersion/RemoteModel.swift
@@ -0,0 +1,7 @@
+public struct Remote: Codable {
+  var details: RemoteDetails
+
+  private enum CodingKeys: String, CodingKey {
+    case details = "dapp-id"
+  }
+}
diff --git a/Sources/ContactFeature/Controllers/ContactController.swift b/Sources/ContactFeature/Controllers/ContactController.swift
index b1e667cecb38dc02c386fcc875317c961674f786..ee9bb011bd4eff7300dcff42ea5af2524434f6ce 100644
--- a/Sources/ContactFeature/Controllers/ContactController.swift
+++ b/Sources/ContactFeature/Controllers/ContactController.swift
@@ -2,14 +2,16 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import Navigation
+import AppCore
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
 import ScrollViewController
 
 public final class ContactController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ContactView()
   private lazy var scrollViewController = ScrollViewController()
@@ -28,7 +30,7 @@ public final class ContactController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.lightContent)
+    statusBar.set(.lightContent)
     navigationController?.navigationBar
       .customize(
         backgroundColor: Asset.neutralBody.color,
diff --git a/Sources/ContactFeature/Controllers/NicknameController.swift b/Sources/ContactFeature/Controllers/NicknameController.swift
index 509f2cba9aba1b2c02699dbb96341908d1b6d5fd..a36ad67dcd7f761d4df829535d17b1d140e2194f 100644
--- a/Sources/ContactFeature/Controllers/NicknameController.swift
+++ b/Sources/ContactFeature/Controllers/NicknameController.swift
@@ -5,83 +5,83 @@ import InputField
 import ScrollViewController
 
 public final class NicknameController: UIViewController {
-    private lazy var screenView = NicknameView()
-
-    private let prefilled: String
-    private let completion: StringClosure
-    private let viewModel = NicknameViewModel()
-    private var cancellables = Set<AnyCancellable>()
-    private let keyboardListener = KeyboardFrameChangeListener(notificationCenter: .default)
-
-    public init(_ prefilled: String, _ completion: @escaping StringClosure) {
-        self.prefilled = prefilled
-        self.completion = completion
-        super.init(nibName: nil, bundle: nil)
+  private lazy var screenView = NicknameView()
+
+  private let prefilled: String
+  private let completion: (String) -> Void
+  private let viewModel = NicknameViewModel()
+  private var cancellables = Set<AnyCancellable>()
+  private let keyboardListener = KeyboardFrameChangeListener(notificationCenter: .default)
+
+  public init(_ prefilled: String, _ completion: @escaping (String) -> Void) {
+    self.prefilled = prefilled
+    self.completion = completion
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    let view = UIView()
+    view.addSubview(screenView)
+
+    screenView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(0)
     }
 
-    required init?(coder: NSCoder) { nil }
+    self.view = view
+  }
 
-    public override func loadView() {
-        let view = UIView()
-        view.addSubview(screenView)
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    setupKeyboard()
+    setupBindings()
 
-        screenView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(0)
-        }
+    screenView.inputField.update(content: prefilled)
+    viewModel.didInput(prefilled)
+  }
 
-        self.view = view
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        setupKeyboard()
-        setupBindings()
-
-        screenView.inputField.update(content: prefilled)
-        viewModel.didInput(prefilled)
-    }
+  private func setupKeyboard() {
+    keyboardListener.keyboardFrameWillChange = { [weak self] keyboard in
+      guard let self else { return }
 
-    private func setupKeyboard() {
-        keyboardListener.keyboardFrameWillChange = { [weak self] keyboard in
-            guard let self else { return }
+      let inset = self.view.frame.height - self.view.convert(keyboard.frame, from: nil).minY
 
-            let inset = self.view.frame.height - self.view.convert(keyboard.frame, from: nil).minY
+      self.screenView.snp.updateConstraints {
+        $0.bottom.equalToSuperview().offset(-inset)
+      }
 
-            self.screenView.snp.updateConstraints {
-                $0.bottom.equalToSuperview().offset(-inset)
-            }
-
-            self.view.setNeedsLayout()
-
-            UIView.animate(withDuration: keyboard.animationDuration) {
-                self.view.layoutIfNeeded()
-            }
-        }
-    }
+      self.view.setNeedsLayout()
 
-    private func setupBindings() {
-        viewModel.state
-            .map(\.status)
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.update(status: $0) }
-            .store(in: &cancellables)
-
-        viewModel.done
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true)
-                completion($0)
-            }.store(in: &cancellables)
-
-        screenView.inputField.textPublisher
-            .sink { [weak viewModel] in viewModel?.didInput($0) }
-            .store(in: &cancellables)
-
-        screenView.saveButton.publisher(for: .touchUpInside)
-            .sink { [weak viewModel] in viewModel?.didTapSave() }
-            .store(in: &cancellables)
+      UIView.animate(withDuration: keyboard.animationDuration) {
+        self.view.layoutIfNeeded()
+      }
     }
+  }
+
+  private func setupBindings() {
+    viewModel.state
+      .map(\.status)
+      .receive(on: DispatchQueue.main)
+      .sink { [weak screenView] in screenView?.update(status: $0) }
+      .store(in: &cancellables)
+
+    viewModel.done
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true)
+        completion($0)
+      }.store(in: &cancellables)
+
+    screenView.inputField.textPublisher
+      .sink { [weak viewModel] in viewModel?.didInput($0) }
+      .store(in: &cancellables)
+
+    screenView.saveButton.publisher(for: .touchUpInside)
+      .sink { [weak viewModel] in viewModel?.didTapSave() }
+      .store(in: &cancellables)
+  }
 }
diff --git a/Sources/ContactFeature/ViewModels/ContactViewModel.swift b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
index 1434570019f0a2be2e3afdc346380944d7f50442..6e20c16e65aea219159179fcea4739f8447f858f 100644
--- a/Sources/ContactFeature/ViewModels/ContactViewModel.swift
+++ b/Sources/ContactFeature/ViewModels/ContactViewModel.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
+import AppCore
 import XXModels
 import Defaults
 import XXClient
+import Dependencies
 import CombineSchedulers
 import XXMessengerClient
-import DI
 
 struct ContactViewState: Equatable {
   var title: String?
@@ -18,10 +19,9 @@ struct ContactViewState: Equatable {
 }
 
 final class ContactViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
-  @Dependency var getFactsFromContact: GetFactsFromContact
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
   
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool
@@ -47,15 +47,11 @@ final class ContactViewModel {
   
   init(_ contact: XXModels.Contact) {
     self.contact = contact
-    
-    let facts = try? getFactsFromContact(contact.marshaled!)
-    let email = facts?.first(where: { $0.type == .email })?.value
-    let phone = facts?.first(where: { $0.type == .phone })?.value
-    
+
     stateRelay.value = .init(
       title: contact.nickname ?? contact.username,
-      email: email,
-      phone: phone,
+      email: contact.email,
+      phone: contact.phone,
       photo: contact.photo != nil ? UIImage(data: contact.photo!) : nil,
       username: contact.username,
       nickname: contact.nickname
@@ -65,50 +61,50 @@ final class ContactViewModel {
   func didChoosePhoto(_ photo: UIImage) {
     stateRelay.value.photo = photo
     contact.photo = photo.jpegData(compressionQuality: 0.0)
-    _ = try? database.saveContact(contact)
+    _ = try? dbManager.getDB().saveContact(contact)
   }
   
   func didTapDelete() {
-    hudController.show()
+    hudManager.show()
     
     do {
       try messenger.e2e.get()!.deleteRequest.partnerId(contact.id)
-      try database.deleteContact(contact)
+      try dbManager.getDB().deleteContact(contact)
       
-      hudController.dismiss()
+      hudManager.hide()
       popToRootRelay.send()
     } catch {
-      hudController.show(.init(error: error))
+      hudManager.show(.init(error: error))
     }
   }
   
   func didTapReject() {
     // TODO: Reject function on the API?
-    _ = try? database.deleteContact(contact)
+    _ = try? dbManager.getDB().deleteContact(contact)
     popRelay.send()
   }
   
   func didTapClear() {
-    _ = try? database.deleteMessages(.init(chat: .direct(myId, contact.id)))
+    _ = try? dbManager.getDB().deleteMessages(.init(chat: .direct(myId, contact.id)))
   }
   
   func didUpdateNickname(_ string: String) {
     contact.nickname = string.isEmpty ? nil : string
     stateRelay.value.title = string.isEmpty ? contact.username : string
-    _ = try? database.saveContact(contact)
+    _ = try? dbManager.getDB().saveContact(contact)
     
     stateRelay.value.nickname = contact.nickname
   }
   
   func didTapResend() {
-    hudController.show()
+    hudManager.show()
     contact.authStatus = .requesting
     
     backgroundScheduler.schedule { [weak self] in
       guard let self else { return }
       
       do {
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
         var includedFacts: [Fact] = []
         let myFacts = try self.messenger.ud.get()!.getFacts()
@@ -131,20 +127,20 @@ final class ContactViewModel {
         )
         
         self.contact.authStatus = .requested
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.popRelay.send()
       } catch {
         self.contact.authStatus = .requestFailed
-        _ = try? self.database.saveContact(self.contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(self.contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
   
   func didTapRequest(with nickname: String) {
-    hudController.show()
+    hudManager.show()
     contact.nickname = nickname
     contact.authStatus = .requesting
     
@@ -152,7 +148,7 @@ final class ContactViewModel {
       guard let self else { return }
       
       do {
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
         var includedFacts: [Fact] = []
         let myFacts = try self.messenger.ud.get()!.getFacts()
@@ -175,20 +171,20 @@ final class ContactViewModel {
         )
         
         self.contact.authStatus = .requested
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.successRelay.send()
       } catch {
         self.contact.authStatus = .requestFailed
-        _ = try? self.database.saveContact(self.contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(self.contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
   
   func didTapAccept(_ nickname: String) {
-    hudController.show()
+    hudManager.show()
     contact.nickname = nickname
     contact.authStatus = .confirming
     
@@ -196,19 +192,19 @@ final class ContactViewModel {
       guard let self else { return }
       
       do {
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
         let _ = try self.messenger.e2e.get()!.confirmReceivedRequest(partner: XXClient.Contact.live(self.contact.marshaled!))
         
         self.contact.authStatus = .friend
-        try self.database.saveContact(self.contact)
+        try self.dbManager.getDB().saveContact(self.contact)
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.popRelay.send()
       } catch {
         self.contact.authStatus = .confirmationFailed
-        _ = try? self.database.saveContact(self.contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(self.contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
diff --git a/Sources/ContactFeature/ViewModels/NicknameViewModel.swift b/Sources/ContactFeature/ViewModels/NicknameViewModel.swift
index 25897d83c215e59b6cfd6233bcb28dc503feb616..6f4cd52b331188a2d10fac1ddff5e0ebaf3d5f80 100644
--- a/Sources/ContactFeature/ViewModels/NicknameViewModel.swift
+++ b/Sources/ContactFeature/ViewModels/NicknameViewModel.swift
@@ -1,6 +1,7 @@
 import Shared
 import Combine
 import InputField
+import AppResources
 
 struct NicknameViewState {
     var nickname: String = ""
diff --git a/Sources/ContactFeature/Views/ContactConfirmedView.swift b/Sources/ContactFeature/Views/ContactConfirmedView.swift
index 472513842beaf5914e6924bf56f56d1b5f2f5b34..7a99fb9f0be8995158fcf17c0f230eb424a32c2d 100644
--- a/Sources/ContactFeature/Views/ContactConfirmedView.swift
+++ b/Sources/ContactFeature/Views/ContactConfirmedView.swift
@@ -1,38 +1,39 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ContactConfirmedView: UIView {
-    let stackView = UIStackView()
-    let clearButton = CapsuleButton()
-    let buttons = SheetCardComponent()
-
-    init() {
-        super.init(frame: .zero)
-
-        clearButton.setStyle(.seeThrough)
-        clearButton.setTitle(Localized.Contact.Confirmed.clear, for: .normal)
-        
-        buttons.set(buttons: [clearButton])
-
-        stackView.axis = .vertical
-        stackView.spacing = 25
-
-        addSubview(stackView)
-        addSubview(buttons)
-        
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(24)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
-
-        buttons.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(stackView.snp.bottom).offset(24)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+  let stackView = UIStackView()
+  let clearButton = CapsuleButton()
+  let buttons = SheetCardComponent()
+
+  init() {
+    super.init(frame: .zero)
+
+    clearButton.setStyle(.seeThrough)
+    clearButton.setTitle(Localized.Contact.Confirmed.clear, for: .normal)
+
+    buttons.set(buttons: [clearButton])
+
+    stackView.axis = .vertical
+    stackView.spacing = 25
+
+    addSubview(stackView)
+    addSubview(buttons)
+
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(24)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+    }
+
+    buttons.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(stackView.snp.bottom).offset(24)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ContactFeature/Views/ContactInProgressView.swift b/Sources/ContactFeature/Views/ContactInProgressView.swift
index 533b5fe893b6f2ab5637dacaab9c2b38cf20881b..2866b6d5d586b1fbc94dfe6479e41d530448980b 100644
--- a/Sources/ContactFeature/Views/ContactInProgressView.swift
+++ b/Sources/ContactFeature/Views/ContactInProgressView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import XXModels
+import AppResources
 
 final class ContactAlmostView: UIView {
   let stack = UIStackView()
diff --git a/Sources/ContactFeature/Views/ContactReceivedView.swift b/Sources/ContactFeature/Views/ContactReceivedView.swift
index 2d29fd46123aab7b37e615fcc31c22cbbd486c06..4678fdb7eb4a2147e18db552fcf2f1705cd9db24 100644
--- a/Sources/ContactFeature/Views/ContactReceivedView.swift
+++ b/Sources/ContactFeature/Views/ContactReceivedView.swift
@@ -1,67 +1,62 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ContactReceivedView: UIView {
-    // MARK: UI
+  let title = UILabel()
+  let icon = UIImageView()
+  let stack = UIStackView()
+  let accept = CapsuleButton()
+  let reject = CapsuleButton()
 
-    let title = UILabel()
-    let icon = UIImageView()
-    let stack = UIStackView()
-    let accept = CapsuleButton()
-    let reject = CapsuleButton()
+  init() {
+    super.init(frame: .zero)
+    setup()
+  }
 
-    // MARK: Lifecycle
+  required init?(coder: NSCoder) { nil }
 
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
+  private func setup() {
+    icon.contentMode = .center
 
-    //  MARK: Private
+    title.textAlignment = .center
+    title.textColor = Asset.neutralBody.color
+    title.text = Localized.Contact.Received.title
+    title.font = Fonts.Mulish.bold.font(size: 24.0)
 
-    private func setup() {
-        icon.contentMode = .center
+    icon.image = Asset.contactRequestPlaceholder.image
 
-        title.textAlignment = .center
-        title.textColor = Asset.neutralBody.color
-        title.text = Localized.Contact.Received.title
-        title.font = Fonts.Mulish.bold.font(size: 24.0)
+    accept.setStyle(.brandColored)
+    accept.setTitle(Localized.Contact.Received.accept, for: .normal)
 
-        icon.image = Asset.contactRequestPlaceholder.image
+    reject.setStyle(.seeThrough)
+    reject.setTitle(Localized.Contact.Received.reject, for: .normal)
 
-        accept.setStyle(.brandColored)
-        accept.setTitle(Localized.Contact.Received.accept, for: .normal)
+    stack.axis = .vertical
+    stack.addArrangedSubview(title)
+    stack.addArrangedSubview(accept)
+    stack.addArrangedSubview(reject)
 
-        reject.setStyle(.seeThrough)
-        reject.setTitle(Localized.Contact.Received.reject, for: .normal)
+    stack.setCustomSpacing(24, after: title)
+    stack.setCustomSpacing(20, after: accept)
 
-        stack.axis = .vertical
-        stack.addArrangedSubview(title)
-        stack.addArrangedSubview(accept)
-        stack.addArrangedSubview(reject)
+    addSubview(icon)
+    addSubview(stack)
 
-        stack.setCustomSpacing(24, after: title)
-        stack.setCustomSpacing(20, after: accept)
+    setupConstraints()
+  }
 
-        addSubview(icon)
-        addSubview(stack)
-
-        setupConstraints()
+  private func setupConstraints() {
+    icon.snp.makeConstraints { make in
+      make.centerX.equalToSuperview()
+      make.bottom.equalTo(stack.snp.top).offset(-30)
     }
 
-    private func setupConstraints() {
-        icon.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-            make.bottom.equalTo(stack.snp.top).offset(-30)
-        }
-
-        stack.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualToSuperview().offset(20)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview().offset(-34)
-        }
+    stack.snp.makeConstraints { make in
+      make.top.greaterThanOrEqualToSuperview().offset(20)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+      make.bottom.equalToSuperview().offset(-34)
     }
+  }
 }
diff --git a/Sources/ContactFeature/Views/ContactScannedView.swift b/Sources/ContactFeature/Views/ContactScannedView.swift
index 840e445cacfbc228705a5616c1b198c86bd534fe..8dd6a118c79bf2e1b736d4214d45a90d2450c5b3 100644
--- a/Sources/ContactFeature/Views/ContactScannedView.swift
+++ b/Sources/ContactFeature/Views/ContactScannedView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ContactScannedView: UIView {
     let title = UILabel()
diff --git a/Sources/ContactFeature/Views/ContactSuccessView.swift b/Sources/ContactFeature/Views/ContactSuccessView.swift
index 616d1b0621274dc6d7b04fb710cef4d4b28140d6..dc610b3ca85802443e376c37ace40c68900f024f 100644
--- a/Sources/ContactFeature/Views/ContactSuccessView.swift
+++ b/Sources/ContactFeature/Views/ContactSuccessView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ContactSuccessView: UIView {
     // MARK: UI
diff --git a/Sources/ContactFeature/Views/ContactView.swift b/Sources/ContactFeature/Views/ContactView.swift
index 08b4a4c6d445f66af68e5ba2637fe26e3c46efe6..059686511eaee49e47ccb3fb9b77156fc5a2427b 100644
--- a/Sources/ContactFeature/Views/ContactView.swift
+++ b/Sources/ContactFeature/Views/ContactView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import XXModels
+import AppResources
 
 final class ContactView: UIView {
     let container = UIView()
diff --git a/Sources/ContactFeature/Views/NicknameView.swift b/Sources/ContactFeature/Views/NicknameView.swift
index 731bdd70a67f940d16e570b7f25b78cd8f1e8e1e..637f5a1fa17a451cc2cc5514a6f2acf268febe64 100644
--- a/Sources/ContactFeature/Views/NicknameView.swift
+++ b/Sources/ContactFeature/Views/NicknameView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class NicknameView: UIView {
     let titleLabel = UILabel()
diff --git a/Sources/ContactListFeature/Controllers/ContactListController.swift b/Sources/ContactListFeature/ContactListController.swift
similarity index 93%
rename from Sources/ContactListFeature/Controllers/ContactListController.swift
rename to Sources/ContactListFeature/ContactListController.swift
index c5a2dbb059953c0a8ed6c5b680ec98a6851261ee..f44b63c0d760b2c0cd55d3a00f972dcb2d1b0e0d 100644
--- a/Sources/ContactListFeature/Controllers/ContactListController.swift
+++ b/Sources/ContactListFeature/ContactListController.swift
@@ -1,12 +1,14 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
-import DI
+import AppCore
+import Dependencies
+import AppResources
+import AppNavigation
 
 public final class ContactListController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ContactListView()
   private lazy var tableController = ContactListTableController(viewModel)
@@ -20,7 +22,7 @@ public final class ContactListController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
   }
 
@@ -105,7 +107,7 @@ public final class ContactListController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentNewGroup(on: navigationController!))
+        navigator.perform(PresentGroupDraft(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
diff --git a/Sources/ContactListFeature/ContactListItemButton.swift b/Sources/ContactListFeature/ContactListItemButton.swift
new file mode 100644
index 0000000000000000000000000000000000000000..009260c7c3a11e54ca25670b56cd6aa3960c9643
--- /dev/null
+++ b/Sources/ContactListFeature/ContactListItemButton.swift
@@ -0,0 +1,61 @@
+import UIKit
+import Shared
+import AppResources
+
+final class ItemButton: UIControl {
+  let titleLabel = UILabel()
+  let iconImageView = UIImageView()
+  let separatorView = UIView()
+  let stackView = UIStackView()
+  let notificationLabel = UILabel()
+
+  init() {
+    super.init(frame: .zero)
+
+    titleLabel.textColor = Asset.brandPrimary.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    separatorView.backgroundColor = Asset.neutralLine.color
+
+    notificationLabel.isHidden = true
+    notificationLabel.layer.cornerRadius = 5
+    notificationLabel.layer.masksToBounds = true
+    notificationLabel.textColor = Asset.neutralWhite.color
+    notificationLabel.backgroundColor = Asset.brandPrimary.color
+    notificationLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    
+    stackView.spacing = 16
+    stackView.addArrangedSubview(iconImageView)
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(notificationLabel)
+    stackView.setCustomSpacing(6, after: titleLabel)
+
+    stackView.isUserInteractionEnabled = false
+    addSubview(stackView)
+    addSubview(separatorView)
+
+    stackView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(12)
+      make.left.equalToSuperview().offset(24)
+      make.bottom.equalTo(separatorView.snp.top).offset(-12)
+    }
+
+    separatorView.snp.makeConstraints { make in
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+      make.bottom.equalToSuperview()
+      make.height.equalTo(1)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setup(title: String, image: UIImage) {
+    titleLabel.text = title
+    iconImageView.image = image
+  }
+
+  func updateNotification(_ count: Int) {
+    notificationLabel.isHidden = count < 1
+    notificationLabel.text = "  \(count)  "
+  }
+}
diff --git a/Sources/ContactListFeature/ContactListTableController.swift b/Sources/ContactListFeature/ContactListTableController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8215991d49982bf7f3780636947fcd7adf575adb
--- /dev/null
+++ b/Sources/ContactListFeature/ContactListTableController.swift
@@ -0,0 +1,83 @@
+import UIKit
+import Shared
+import Combine
+import XXModels
+import AppResources
+
+final class ContactListTableController: UITableViewController {
+  private var collation = UILocalizedIndexedCollation.current()
+  private var sections: [[Contact]] = [] {
+    didSet { self.tableView.reloadData() }
+  }
+  
+  private let viewModel: ContactListViewModel
+  private var cancellables = Set<AnyCancellable>()
+  private let tapRelay = PassthroughSubject<Contact, Never>()
+  
+  var didTap: AnyPublisher<Contact, Never> { tapRelay.eraseToAnyPublisher() }
+  
+  override func viewDidLoad() {
+    super.viewDidLoad()
+    setupTableView()
+  }
+  
+  init(_ viewModel: ContactListViewModel) {
+    self.viewModel = viewModel
+    super.init(style: .grouped)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  private func setupTableView() {
+    tableView.separatorStyle = .none
+    tableView.register(AvatarCell.self)
+    tableView.backgroundColor = Asset.neutralWhite.color
+    tableView.sectionIndexColor = Asset.neutralDark.color
+    tableView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)
+    
+    viewModel.contacts
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        let results = IndexedListCollator().sectioned(items: $0)
+        self.collation = results.collation
+        self.sections = results.sections
+      }.store(in: &cancellables)
+  }
+  
+  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+    let cell: AvatarCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
+    let contact = sections[indexPath.section][indexPath.row]
+    let name = (contact.nickname ?? contact.username) ?? "Fetching username..."
+    
+    cell.setup(title: name, image: contact.photo)
+    return cell
+  }
+  
+  override func numberOfSections(in: UITableView) -> Int {
+    sections.count
+  }
+  
+  override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
+    sections[section].count
+  }
+  
+  override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
+    tapRelay.send(sections[indexPath.section][indexPath.row])
+  }
+  
+  override func sectionIndexTitles(for: UITableView) -> [String]? {
+    collation.sectionIndexTitles
+  }
+  
+  override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
+    collation.sectionTitles[section]
+  }
+  
+  override func tableView(_: UITableView, sectionForSectionIndexTitle: String, at index: Int) -> Int {
+    collation.section(forSectionIndexTitle: index)
+  }
+  
+  override func tableView(_: UITableView, heightForRowAt: IndexPath) -> CGFloat {
+    64
+  }
+}
diff --git a/Sources/ContactListFeature/ContactListView.swift b/Sources/ContactListFeature/ContactListView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..75ce0cb079969051c4fef0598a417dfcf7279ec6
--- /dev/null
+++ b/Sources/ContactListFeature/ContactListView.swift
@@ -0,0 +1,73 @@
+import UIKit
+import Shared
+import AppResources
+
+final class ContactListView: UIView {
+  let newGroupButton = ItemButton()
+  let requestsButton = ItemButton()
+  let topStackView = UIStackView()
+  let stackView = UIStackView()
+  let emptyTitleLabel = UILabel()
+  let searchButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+    setup()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  private func setup() {
+    backgroundColor = Asset.neutralWhite.color
+
+    requestsButton.separatorView.isHidden = true
+    requestsButton.setup(title: "Requests", image: Asset.contactListRequests.image)
+    newGroupButton.setup(title: Localized.ContactList.newGroup, image: Asset.contactListNewGroup.image)
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.lineHeightMultiple = 1.2
+    paragraph.alignment = .center
+
+    emptyTitleLabel.attributedText = NSAttributedString(
+      string: Localized.ContactList.Empty.title,
+      attributes: [
+        .paragraphStyle: paragraph,
+        .foregroundColor: Asset.neutralActive.color,
+        .font: Fonts.Mulish.bold.font(size: 24.0) as UIFont
+      ]
+    )
+    emptyTitleLabel.numberOfLines = 0
+
+    searchButton.setStyle(.brandColored)
+    searchButton.setTitle(Localized.ContactList.Empty.action, for: .normal)
+
+    stackView.spacing = 24
+    stackView.axis = .vertical
+    stackView.alignment = .center
+    stackView.addArrangedSubview(emptyTitleLabel)
+    stackView.addArrangedSubview(searchButton)
+
+    topStackView.axis = .vertical
+    topStackView.addArrangedSubview(newGroupButton)
+    topStackView.addArrangedSubview(requestsButton)
+
+    addSubview(topStackView)
+    addSubview(stackView)
+
+    setupConstraints()
+  }
+
+  private func setupConstraints() {
+    topStackView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(20)
+      make.left.equalToSuperview()
+      make.right.equalToSuperview()
+    }
+
+    stackView.snp.makeConstraints { make in
+      make.centerY.equalToSuperview()
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+    }
+  }
+}
diff --git a/Sources/ContactListFeature/ContactListViewModel.swift b/Sources/ContactListFeature/ContactListViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..3e509accc5cfd7c71e76ec7e6dc814da5a63af9a
--- /dev/null
+++ b/Sources/ContactListFeature/ContactListViewModel.swift
@@ -0,0 +1,63 @@
+import Combine
+import XXModels
+import Defaults
+import ReportingFeature
+import XXMessengerClient
+
+import Foundation
+import XXClient
+
+import AppCore
+import Dependencies
+
+final class ContactListViewModel {
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  var myId: Data {
+    try! messenger.e2e.get()!.getContact().getId()
+  }
+
+  var contacts: AnyPublisher<[XXModels.Contact], Never> {
+    let query = Contact.Query(
+      authStatus: [.friend],
+      isBlocked: reportingStatus.isEnabled() ? false : nil,
+      isBanned: reportingStatus.isEnabled() ? false: nil
+    )
+
+    return try! dbManager.getDB().fetchContactsPublisher(query)
+      .replaceError(with: [])
+      .map { $0.filter { $0.id != self.myId }}
+      .eraseToAnyPublisher()
+  }
+
+  var requestCount: AnyPublisher<Int, Never> {
+    let groupQuery = Group.Query(
+      authStatus: [.pending],
+      isLeaderBlocked: reportingStatus.isEnabled() ? false : nil,
+      isLeaderBanned: reportingStatus.isEnabled() ? false : nil
+    )
+
+    let contactsQuery = Contact.Query(
+      authStatus: [
+        .verified,
+        .confirming,
+        .confirmationFailed,
+        .verificationFailed,
+        .verificationInProgress
+      ],
+      isBlocked: reportingStatus.isEnabled() ? false : nil,
+      isBanned: reportingStatus.isEnabled() ? false : nil
+    )
+
+    return Publishers.CombineLatest(
+      try! dbManager.getDB().fetchContactsPublisher(contactsQuery)
+        .replaceError(with: []),
+      try! dbManager.getDB().fetchGroupsPublisher(groupQuery)
+        .replaceError(with: [])
+    )
+    .map { $0.0.count + $0.1.count }
+    .eraseToAnyPublisher()
+  }
+}
diff --git a/Sources/ContactListFeature/Controllers/ContactListTableController.swift b/Sources/ContactListFeature/Controllers/ContactListTableController.swift
deleted file mode 100644
index 0e456781aadc10fe5ce5c8e98b2444720a540546..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Controllers/ContactListTableController.swift
+++ /dev/null
@@ -1,82 +0,0 @@
-import UIKit
-import Shared
-import Combine
-import XXModels
-
-final class ContactListTableController: UITableViewController {
-    private var collation = UILocalizedIndexedCollation.current()
-    private var sections: [[Contact]] = [] {
-        didSet { self.tableView.reloadData() }
-    }
-
-    private let viewModel: ContactListViewModel
-    private var cancellables = Set<AnyCancellable>()
-    private let tapRelay = PassthroughSubject<Contact, Never>()
-
-    var didTap: AnyPublisher<Contact, Never> { tapRelay.eraseToAnyPublisher() }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupTableView()
-    }
-
-    init(_ viewModel: ContactListViewModel) {
-        self.viewModel = viewModel
-        super.init(style: .grouped)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setupTableView() {
-        tableView.separatorStyle = .none
-        tableView.register(AvatarCell.self)
-        tableView.backgroundColor = Asset.neutralWhite.color
-        tableView.sectionIndexColor = Asset.neutralDark.color
-        tableView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)
-
-        viewModel.contacts
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                let results = IndexedListCollator().sectioned(items: $0)
-                self.collation = results.collation
-                self.sections = results.sections
-            }.store(in: &cancellables)
-    }
-
-    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell: AvatarCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
-        let contact = sections[indexPath.section][indexPath.row]
-        let name = (contact.nickname ?? contact.username) ?? "Fetching username..."
-
-        cell.setup(title: name, image: contact.photo)
-        return cell
-    }
-
-    override func numberOfSections(in: UITableView) -> Int {
-        sections.count
-    }
-
-    override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
-        sections[section].count
-    }
-
-    override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tapRelay.send(sections[indexPath.section][indexPath.row])
-    }
-
-    override func sectionIndexTitles(for: UITableView) -> [String]? {
-        collation.sectionIndexTitles
-    }
-
-    override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
-        collation.sectionTitles[section]
-    }
-
-    override func tableView(_: UITableView, sectionForSectionIndexTitle: String, at index: Int) -> Int {
-        collation.section(forSectionIndexTitle: index)
-    }
-
-    override func tableView(_: UITableView, heightForRowAt: IndexPath) -> CGFloat {
-        64
-    }
-}
diff --git a/Sources/ContactListFeature/Controllers/CreateDrawerController.swift b/Sources/ContactListFeature/Controllers/CreateDrawerController.swift
deleted file mode 100644
index 4ba7213d8a117cd7650fa992f40ccc8e43ab2924..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Controllers/CreateDrawerController.swift
+++ /dev/null
@@ -1,89 +0,0 @@
-import UIKit
-import Shared
-import Combine
-
-public final class CreateDrawerController: UIViewController {
-    private lazy var screenView = CreateDrawerView()
-
-    private let selectedCount: Int
-    private let viewModel = CreateDrawerViewModel()
-    private let completion: (String, String?) -> Void
-    private var cancellables = Set<AnyCancellable>()
-
-    public init(_ count: Int, _ completion: @escaping (String, String?) -> Void) {
-        self.selectedCount = count
-        self.completion = completion
-        super.init(nibName: nil, bundle: nil)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func loadView() {
-        let view = UIView()
-        view.addSubview(screenView)
-
-        screenView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(0)
-        }
-
-        self.view = view
-    }
-
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        screenView.set(count: selectedCount) {
-            // TODO: ⚠️
-        }
-
-        setupBindings()
-    }
-
-    private func setupBindings() {
-        viewModel.statePublisher
-            .map(\.status)
-            .receive(on: DispatchQueue.main)
-            .sink { [weak screenView] in screenView?.update(status: $0) }
-            .store(in: &cancellables)
-
-        viewModel.donePublisher
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in
-                dismiss(animated: true)
-                completion($0.0, $0.1)
-            }.store(in: &cancellables)
-
-        screenView.cancelButton
-            .publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in dismiss(animated: true) }
-            .store(in: &cancellables)
-
-        screenView.inputField
-            .textPublisher
-            .sink { [weak viewModel] in viewModel?.didInput($0) }
-            .store(in: &cancellables)
-
-        screenView.otherInputField
-            .textPublisher
-            .sink { [weak viewModel] in viewModel?.didOtherInput($0) }
-            .store(in: &cancellables)
-
-        screenView.inputField
-            .returnPublisher
-            .sink { [unowned self] in screenView.inputField.endEditing(true) }
-            .store(in: &cancellables)
-
-        screenView.otherInputField
-            .returnPublisher
-            .sink { [unowned self] in screenView.otherInputField.endEditing(true) }
-            .store(in: &cancellables)
-
-        screenView.createButton
-            .publisher(for: .touchUpInside)
-            .sink { [weak viewModel] in viewModel?.didTapCreate() }
-            .store(in: &cancellables)
-    }
-}
diff --git a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift b/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift
deleted file mode 100644
index 838a7b12557279a3833c1c2d955e3719d6c74561..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/ViewModels/ContactListViewModel.swift
+++ /dev/null
@@ -1,61 +0,0 @@
-import Combine
-import XXModels
-import Defaults
-import ReportingFeature
-import DI
-import XXMessengerClient
-
-import Foundation
-import XXClient
-
-final class ContactListViewModel {
-    @Dependency var database: Database
-    @Dependency var messenger: Messenger
-    @Dependency var reportingStatus: ReportingStatus
-
-    var myId: Data {
-        try! messenger.e2e.get()!.getContact().getId()
-    }
-
-    var contacts: AnyPublisher<[XXModels.Contact], Never> {
-        let query = Contact.Query(
-            authStatus: [.friend],
-            isBlocked: reportingStatus.isEnabled() ? false : nil,
-            isBanned: reportingStatus.isEnabled() ? false: nil
-        )
-
-        return database.fetchContactsPublisher(query)
-        .replaceError(with: [])
-            .map { $0.filter { $0.id != self.myId }}
-            .eraseToAnyPublisher()
-    }
-
-    var requestCount: AnyPublisher<Int, Never> {
-        let groupQuery = Group.Query(
-            authStatus: [.pending],
-            isLeaderBlocked: reportingStatus.isEnabled() ? false : nil,
-            isLeaderBanned: reportingStatus.isEnabled() ? false : nil
-        )
-
-        let contactsQuery = Contact.Query(
-            authStatus: [
-                .verified,
-                .confirming,
-                .confirmationFailed,
-                .verificationFailed,
-                .verificationInProgress
-            ],
-            isBlocked: reportingStatus.isEnabled() ? false : nil,
-            isBanned: reportingStatus.isEnabled() ? false : nil
-        )
-
-        return Publishers.CombineLatest(
-            database.fetchContactsPublisher(contactsQuery)
-              .replaceError(with: []),
-            database.fetchGroupsPublisher(groupQuery)
-              .replaceError(with: [])
-        )
-        .map { $0.0.count + $0.1.count }
-        .eraseToAnyPublisher()
-    }
-}
diff --git a/Sources/ContactListFeature/ViewModels/CreateDrawerViewModel.swift b/Sources/ContactListFeature/ViewModels/CreateDrawerViewModel.swift
deleted file mode 100644
index b47569594d82edaf5b9b92dc9ab0fc6d6fef040a..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/ViewModels/CreateDrawerViewModel.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-import Shared
-import Combine
-import InputField
-
-struct CreateDrawerViewState {
-    var welcome: String?
-    var groupName: String = ""
-    var status: InputField.ValidationStatus = .unknown(nil)
-}
-
-final class CreateDrawerViewModel {
-    var statePublisher: AnyPublisher<CreateDrawerViewState, Never> {
-        stateSubject.eraseToAnyPublisher()
-    }
-
-    var donePublisher: AnyPublisher<(String, String?), Never> {
-        doneSubject.eraseToAnyPublisher()
-    }
-
-    private let doneSubject = PassthroughSubject<(String, String?), Never>()
-    private let stateSubject = CurrentValueSubject<CreateDrawerViewState, Never>(.init())
-
-    func didInput(_ string: String) {
-        stateSubject.value.groupName = string
-        validate()
-    }
-
-    func didOtherInput(_ string: String) {
-        stateSubject.value.welcome = string
-    }
-
-    func didTapCreate() {
-        let name = stateSubject.value.groupName.trimmingCharacters(in: .whitespacesAndNewlines)
-        let welcome = stateSubject.value.welcome
-        doneSubject.send((name, welcome))
-    }
-
-    private func validate() {
-        let value = stateSubject.value.groupName.trimmingCharacters(in: .whitespacesAndNewlines)
-
-        guard value.count >= 4 else {
-            stateSubject.value.status = .invalid(Localized.CreateGroup.Drawer.minimum)
-            return
-        }
-
-        guard value.count < 21 else {
-            stateSubject.value.status = .invalid(Localized.CreateGroup.Drawer.maximum)
-            return
-        }
-
-        stateSubject.value.status = .valid(nil)
-    }
-}
diff --git a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift b/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
deleted file mode 100644
index 74d9745b35ebd188dff4cf9a74115bb50e4d7c55..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/ViewModels/CreateGroupViewModel.swift
+++ /dev/null
@@ -1,141 +0,0 @@
-import UIKit
-import Shared
-import Combine
-import XXModels
-import Defaults
-import XXClient
-import ReportingFeature
-import CombineSchedulers
-import XXMessengerClient
-import DI
-
-final class CreateGroupViewModel {
-  @KeyObject(.username, defaultValue: "") var username: String
-
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var groupManager: GroupChat
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
-
-  var myId: Data {
-    try! messenger.e2e.get()!.getContact().getId()
-  }
-
-  var selected: AnyPublisher<[XXModels.Contact], Never> {
-    selectedContactsRelay.eraseToAnyPublisher()
-  }
-
-  var contacts: AnyPublisher<[XXModels.Contact], Never> {
-    contactsRelay.eraseToAnyPublisher()
-  }
-
-  var info: AnyPublisher<GroupInfo, Never> {
-    infoRelay.eraseToAnyPublisher()
-  }
-
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue>
-  = DispatchQueue.global().eraseToAnyScheduler()
-
-  private var allContacts = [XXModels.Contact]()
-  private var cancellables = Set<AnyCancellable>()
-  private let infoRelay = PassthroughSubject<GroupInfo, Never>()
-  private let contactsRelay = CurrentValueSubject<[XXModels.Contact], Never>([])
-  private let selectedContactsRelay = CurrentValueSubject<[XXModels.Contact], Never>([])
-
-  init() {
-    let query = Contact.Query(
-      authStatus: [.friend],
-      isBlocked: reportingStatus.isEnabled() ? false : nil,
-      isBanned: reportingStatus.isEnabled() ? false : nil
-    )
-
-    database.fetchContactsPublisher(query)
-      .replaceError(with: [])
-      .map { $0.filter { $0.id != self.myId }}
-      .map { $0.sorted(by: { $0.username! < $1.username! })}
-      .sink { [unowned self] in
-        allContacts = $0
-        contactsRelay.send($0)
-      }.store(in: &cancellables)
-  }
-
-  // MARK: Public
-
-  func didSelect(contact: XXModels.Contact) {
-    if selectedContactsRelay.value.contains(contact) {
-      selectedContactsRelay.value.removeAll { $0.username == contact.username }
-    } else {
-      selectedContactsRelay.value.append(contact)
-    }
-  }
-
-  func filter(_ text: String) {
-    guard text.isEmpty == false else {
-      contactsRelay.send(allContacts)
-      return
-    }
-
-    contactsRelay.send(
-      allContacts.filter {
-        ($0.username ?? "").contains(text.lowercased())
-      }
-    )
-  }
-
-  func create(name: String, welcome: String?, members: [XXModels.Contact]) {
-    hudController.show()
-
-    backgroundScheduler.schedule { [weak self] in
-      guard let self else { return }
-
-      do {
-        let report = try self.groupManager.makeGroup(
-          membership: members.map(\.id),
-          message: welcome?.data(using: .utf8),
-          name: name.data(using: .utf8)
-        )
-
-        let group = Group(
-          id: report.id,
-          name: name,
-          leaderId: self.myId,
-          createdAt: Date(),
-          authStatus: .participating,
-          serialized: try report.encode() // ?
-        )
-
-        _ = try self.database.saveGroup(group)
-
-        if let welcomeMessage = welcome {
-          try self.database.saveMessage(
-            Message(
-              senderId: self.myId,
-              recipientId: nil,
-              groupId: group.id,
-              date: group.createdAt,
-              status: .sent,
-              isUnread: false,
-              text: welcomeMessage,
-              replyMessageId: nil,
-              roundURL: nil,
-              fileTransferId: nil
-            )
-          )
-        }
-
-        try members
-          .map { GroupMember(groupId: group.id, contactId: $0.id) }
-          .forEach { try self.database.saveGroupMember($0) }
-
-        let query = GroupInfo.Query(groupId: group.id)
-        let info = try self.database.fetchGroupInfos(query).first
-
-        self.infoRelay.send(info!)
-        self.hudController.dismiss()
-      } catch {
-        self.hudController.show(.init(error: error))
-      }
-    }
-  }
-}
diff --git a/Sources/ContactListFeature/Views/ContactListItemButton.swift b/Sources/ContactListFeature/Views/ContactListItemButton.swift
deleted file mode 100644
index c498f27ab9429fade4721e95b5fca6f3a73bdca7..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Views/ContactListItemButton.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-import UIKit
-import Shared
-
-final class ItemButton: UIControl {
-    let titleLabel = UILabel()
-    let iconImageView = UIImageView()
-    let separatorView = UIView()
-    let stackView = UIStackView()
-    let notificationLabel = UILabel()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.textColor = Asset.brandPrimary.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        notificationLabel.isHidden = true
-        notificationLabel.layer.cornerRadius = 5
-        notificationLabel.layer.masksToBounds = true
-        notificationLabel.textColor = Asset.neutralWhite.color
-        notificationLabel.backgroundColor = Asset.brandPrimary.color
-        notificationLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-
-        stackView.spacing = 16
-        stackView.addArrangedSubview(iconImageView)
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(notificationLabel)
-        stackView.setCustomSpacing(6, after: titleLabel)
-
-        stackView.isUserInteractionEnabled = false
-        addSubview(stackView)
-        addSubview(separatorView)
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(12)
-            make.left.equalToSuperview().offset(24)
-            make.bottom.equalTo(separatorView.snp.top).offset(-12)
-        }
-
-        separatorView.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview()
-            make.height.equalTo(1)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setup(title: String, image: UIImage) {
-        titleLabel.text = title
-        iconImageView.image = image
-    }
-
-    func updateNotification(_ count: Int) {
-        notificationLabel.isHidden = count < 1
-        notificationLabel.text = "  \(count)  "
-    }
-}
diff --git a/Sources/ContactListFeature/Views/ContactListView.swift b/Sources/ContactListFeature/Views/ContactListView.swift
deleted file mode 100644
index e7a52a717346d43bb2551eac86839d796a9c78c1..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Views/ContactListView.swift
+++ /dev/null
@@ -1,72 +0,0 @@
-import UIKit
-import Shared
-
-final class ContactListView: UIView {
-    let newGroupButton = ItemButton()
-    let requestsButton = ItemButton()
-    let topStackView = UIStackView()
-    let stackView = UIStackView()
-    let emptyTitleLabel = UILabel()
-    let searchButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setup() {
-        backgroundColor = Asset.neutralWhite.color
-
-        requestsButton.separatorView.isHidden = true
-        requestsButton.setup(title: "Requests", image: Asset.contactListRequests.image)
-        newGroupButton.setup(title: Localized.ContactList.newGroup, image: Asset.contactListNewGroup.image)
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.lineHeightMultiple = 1.2
-        paragraph.alignment = .center
-
-        emptyTitleLabel.attributedText = NSAttributedString(
-            string: Localized.ContactList.Empty.title,
-            attributes: [
-                .paragraphStyle: paragraph,
-                .foregroundColor: Asset.neutralActive.color,
-                .font: Fonts.Mulish.bold.font(size: 24.0) as UIFont
-            ]
-        )
-        emptyTitleLabel.numberOfLines = 0
-
-        searchButton.setStyle(.brandColored)
-        searchButton.setTitle(Localized.ContactList.Empty.action, for: .normal)
-
-        stackView.spacing = 24
-        stackView.axis = .vertical
-        stackView.alignment = .center
-        stackView.addArrangedSubview(emptyTitleLabel)
-        stackView.addArrangedSubview(searchButton)
-
-        topStackView.axis = .vertical
-        topStackView.addArrangedSubview(newGroupButton)
-        topStackView.addArrangedSubview(requestsButton)
-
-        addSubview(topStackView)
-        addSubview(stackView)
-
-        setupConstraints()
-    }
-
-    private func setupConstraints() {
-        topStackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.centerY.equalToSuperview()
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
-    }
-}
diff --git a/Sources/ContactListFeature/Views/CreateDrawerView.swift b/Sources/ContactListFeature/Views/CreateDrawerView.swift
deleted file mode 100644
index 618ce7c94b4ed11109294b82bda47c8e17d98820..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Views/CreateDrawerView.swift
+++ /dev/null
@@ -1,106 +0,0 @@
-import UIKit
-import Shared
-import InputField
-
-final class CreateDrawerView: UIView {
-    let titleLabel = UILabel()
-    let subtitleView = TextWithInfoView()
-    let inputField = InputField()
-    let otherInputField = InputField()
-    let stackView = UIStackView()
-    let createButton = CapsuleButton()
-    let cancelButton = CapsuleButton()
-
-    var didTapInfo: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-
-        layer.cornerRadius = 40
-        backgroundColor = Asset.neutralWhite.color
-        layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
-
-        titleLabel.textAlignment = .left
-        titleLabel.text = Localized.CreateGroup.Drawer.title
-        titleLabel.font = Fonts.Mulish.bold.font(size: 26.0)
-        titleLabel.textColor = Asset.neutralActive.color
-
-        inputField.setup(
-            style: .regular,
-            title: Localized.CreateGroup.Drawer.input,
-            placeholder: Localized.CreateGroup.Drawer.placeholder,
-            leftView: .image(Asset.personGray.image),
-            accessibility: Localized.Accessibility.CreateGroup.Drawer.input,
-            subtitleColor: Asset.neutralDisabled.color
-        )
-
-        otherInputField.setup(
-            style: .regular,
-            title: Localized.CreateGroup.Drawer.otherInput,
-            placeholder: Localized.CreateGroup.Drawer.otherPlaceholder,
-            leftView: .image(Asset.balloon.image),
-            accessibility: Localized.Accessibility.CreateGroup.Drawer.otherInput,
-            subtitleColor: Asset.neutralDisabled.color
-        )
-
-        createButton.set(
-            style: .brandColored,
-            title: Localized.CreateGroup.Drawer.action,
-            accessibility: Localized.Accessibility.CreateGroup.Drawer.create
-        )
-
-        cancelButton.set(
-            style: .seeThrough,
-            title: Localized.CreateGroup.Drawer.cancel
-        )
-
-        stackView.spacing = 20
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(subtitleView)
-        stackView.addArrangedSubview(inputField)
-        stackView.addArrangedSubview(otherInputField)
-        stackView.addArrangedSubview(createButton)
-        stackView.addArrangedSubview(cancelButton)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(60)
-            $0.left.equalToSuperview().offset(50)
-            $0.right.equalToSuperview().offset(-50)
-            $0.bottom.equalToSuperview().offset(-70)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func set(count: Int, didTap: @escaping () -> Void) {
-        self.didTapInfo = didTap
-
-        let paragraphStyle = NSMutableParagraphStyle()
-        paragraphStyle.alignment = .left
-        paragraphStyle.lineHeightMultiple = 1.1
-
-        subtitleView.setup(
-            text: Localized.CreateGroup.Drawer.subtitle("\(count)"),
-            attributes: [
-                .paragraphStyle: paragraphStyle,
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.semiBold.font(size: 14.0) as Any
-            ],
-            didTapInfo: { [weak self] in self?.didTapInfo?() }
-        )
-    }
-
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-
-        switch status {
-        case .valid:
-            createButton.isEnabled = true
-        case .invalid, .unknown:
-            createButton.isEnabled = false
-        }
-    }
-}
diff --git a/Sources/ContactListFeature/Views/CreateGroupCollectionCell.swift b/Sources/ContactListFeature/Views/CreateGroupCollectionCell.swift
deleted file mode 100644
index 1717365300ab0ae52380cc47e6073f8118684957..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Views/CreateGroupCollectionCell.swift
+++ /dev/null
@@ -1,80 +0,0 @@
-import UIKit
-import Shared
-import Combine
-
-final class CreateGroupCollectionCell: UICollectionViewCell {
-    let titleLabel = UILabel()
-    let removeButton = UIButton()
-    let upperView = UIView()
-    let avatarView = AvatarView()
-
-    var didTapRemove: (() -> Void)?
-    var cancellables = Set<AnyCancellable>()
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-
-        titleLabel.numberOfLines = 2
-        titleLabel.lineBreakMode = .byWordWrapping
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralDark.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        removeButton.layer.cornerRadius = 9
-        removeButton.backgroundColor = Asset.accentDanger.color
-        removeButton.setImage(Asset.contactListAvatarRemove.image, for: .normal)
-
-        upperView.addSubview(avatarView)
-        contentView.addSubview(titleLabel)
-        contentView.addSubview(upperView)
-        contentView.addSubview(removeButton)
-
-        upperView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-        }
-
-        avatarView.snp.makeConstraints {
-            $0.width.equalTo(48)
-            $0.height.equalTo(48)
-            $0.top.equalToSuperview().offset(4)
-            $0.left.equalToSuperview().offset(4)
-            $0.right.equalToSuperview().offset(-4)
-            $0.bottom.equalToSuperview().offset(-4)
-        }
-
-        removeButton.snp.makeConstraints {
-            $0.centerY.equalTo(avatarView.snp.top).offset(5)
-            $0.centerX.equalTo(avatarView.snp.right).offset(-5)
-            $0.width.equalTo(18)
-            $0.height.equalTo(18)
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(upperView.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        titleLabel.text = nil
-        avatarView.prepareForReuse()
-        cancellables.removeAll()
-    }
-
-    func setup(title: String, image: Data?) {
-        titleLabel.text = title
-        avatarView.setupProfile(title: title, image: image, size: .large)
-        cancellables.removeAll()
-
-        removeButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in didTapRemove?() }
-            .store(in: &cancellables)
-    }
-}
diff --git a/Sources/ContactListFeature/Views/CreateGroupView.swift b/Sources/ContactListFeature/Views/CreateGroupView.swift
deleted file mode 100644
index 0f7bd57962bed1fd6930bb6e1cd62fe2c618b01b..0000000000000000000000000000000000000000
--- a/Sources/ContactListFeature/Views/CreateGroupView.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-import UIKit
-import Shared
-import SnapKit
-
-final class CreateGroupView: UIView {
-    let stackView = UIStackView()
-    let tableView = UITableView()
-    let searchComponent = SearchComponent()
-    lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
-
-    let layout: UICollectionViewFlowLayout = {
-        let layout = UICollectionViewFlowLayout()
-        layout.minimumInteritemSpacing = 45
-        layout.itemSize = CGSize(width: 56, height: 100)
-        layout.scrollDirection = .horizontal
-        return layout
-    }()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        tableView.separatorStyle = .none
-        tableView.tintColor = Asset.brandPrimary.color
-        tableView.backgroundColor = Asset.neutralWhite.color
-        tableView.allowsMultipleSelectionDuringEditing = true
-        tableView.setEditing(true, animated: true)
-
-        searchComponent.set(
-            placeholder: "Search connections",
-            imageAtRight: UIImage.color(.clear)
-        )
-
-        collectionView.backgroundColor = Asset.neutralWhite.color
-        collectionView.contentInset = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 30)
-
-        stackView.spacing = 31
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(collectionView)
-        stackView.addArrangedSubview(tableView)
-
-        addSubview(stackView)
-        addSubview(searchComponent)
-
-        searchComponent.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(20)
-            make.right.equalToSuperview().offset(-20)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalTo(searchComponent.snp.bottom).offset(20)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
-
-        collectionView.snp.makeConstraints { $0.height.equalTo(100) }
-    }
-
-    required init?(coder: NSCoder) { nil }
-}
diff --git a/Sources/CountryListFeature/CountryListController.swift b/Sources/CountryListFeature/CountryListController.swift
index f7c11b93853371b1ccf191b32abfe367ca59b237..dd6ad4e65985464e7ae3c323a30df35da6033ab9 100644
--- a/Sources/CountryListFeature/CountryListController.swift
+++ b/Sources/CountryListFeature/CountryListController.swift
@@ -1,12 +1,12 @@
 import UIKit
 import Shared
 import Combine
+import AppCore
 import AppResources
-import StatusBarFeature
-import ComposableArchitecture
+import Dependencies
 
 public final class CountryListController: UIViewController, UITableViewDelegate {
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = CountryListView()
 
@@ -24,7 +24,7 @@ public final class CountryListController: UIViewController, UITableViewDelegate
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
   }
 
   public override func loadView() {
diff --git a/Sources/CrashReport/CrashReport.swift b/Sources/CrashReport/CrashReport.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b5eceb577f093b6d61aafe6290cfe943c597ed36
--- /dev/null
+++ b/Sources/CrashReport/CrashReport.swift
@@ -0,0 +1,26 @@
+import Firebase
+import CrashReporting
+import FirebaseCrashlytics
+import XCTestDynamicOverlay
+
+public struct CrashReport {
+  public var configure: () -> Void
+  public var sendError: (NSError) -> Void
+  public var setEnabled: (Bool) -> Void
+}
+
+extension CrashReport {
+  public static let live = CrashReport(
+    configure: FirebaseApp.configure,
+    sendError: Crashlytics.crashlytics().record(error:),
+    setEnabled: Crashlytics.crashlytics().setCrashlyticsCollectionEnabled
+  )
+}
+
+extension CrashReport {
+  public static let unimplemented = CrashReport(
+    configure: XCTUnimplemented("\(Self.self)"),
+    sendError: XCTUnimplemented("\(Self.self)"),
+    setEnabled: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/CrashReport/Dependency.swift b/Sources/CrashReport/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ee81581b77eac6a15c8ca9e4d5044a644a7b4c13
--- /dev/null
+++ b/Sources/CrashReport/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum CrashReportDependencyKey: DependencyKey {
+  static let liveValue: CrashReport = .live
+  static let testValue: CrashReport = .unimplemented
+}
+
+extension DependencyValues {
+  public var crashReport: CrashReport {
+    get { self[CrashReportDependencyKey.self] }
+    set { self[CrashReportDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/CrashReporting/CrashReporter.swift b/Sources/CrashReporting/CrashReporter.swift
deleted file mode 100644
index e83c1c54b0f765442b9f31c5c779c86096a92db7..0000000000000000000000000000000000000000
--- a/Sources/CrashReporting/CrashReporter.swift
+++ /dev/null
@@ -1,25 +0,0 @@
-import Foundation
-
-public struct CrashReporter {
-  public var configure: () -> Void
-  public var sendError: (NSError) -> Void
-  public var setEnabled: (Bool) -> Void
-
-  public init(
-    configure: @escaping () -> Void,
-    sendError: @escaping (NSError) -> Void,
-    setEnabled: @escaping (Bool) -> Void
-  ) {
-    self.configure = configure
-    self.sendError = sendError
-    self.setEnabled = setEnabled
-  }
-}
-
-public extension CrashReporter {
-  static let noop = Self(
-    configure: {},
-    sendError: { _ in },
-    setEnabled: { _ in }
-  )
-}
diff --git a/Sources/CrashService/CrashService.swift b/Sources/CrashService/CrashService.swift
deleted file mode 100644
index 4226369deeb3db598fee81058dbd139ff0dc1c2b..0000000000000000000000000000000000000000
--- a/Sources/CrashService/CrashService.swift
+++ /dev/null
@@ -1,11 +0,0 @@
-import Firebase
-import CrashReporting
-import FirebaseCrashlytics
-
-public extension CrashReporter {
-  static let live = Self(
-    configure: { FirebaseApp.configure() },
-    sendError: { Crashlytics.crashlytics().record(error: $0) },
-    setEnabled: { Crashlytics.crashlytics().setCrashlyticsCollectionEnabled($0) }
-  )
-}
diff --git a/Sources/CreateGroupFeature/CreateGroupController.swift b/Sources/CreateGroupFeature/CreateGroupController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ad7303364f56d0dbd7b840f3803cb066f8be2578
--- /dev/null
+++ b/Sources/CreateGroupFeature/CreateGroupController.swift
@@ -0,0 +1,87 @@
+import UIKit
+import Combine
+import XXModels
+
+public final class CreateGroupController: UIViewController {
+  private lazy var screenView = CreateGroupView()
+
+  private let groupMembers: [Contact]
+  private let viewModel = CreateGroupViewModel()
+  private var cancellables = Set<AnyCancellable>()
+
+  public init(_ groupMembers: [Contact]) {
+    self.groupMembers = groupMembers
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func loadView() {
+    view = screenView
+  }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    screenView.set(count: groupMembers.count, didTap: {})
+
+    viewModel
+      .statePublisher
+      .map(\.status)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        screenView.update(status: $0)
+      }.store(in: &cancellables)
+
+    viewModel
+      .statePublisher
+      .map(\.shouldDismiss)
+      .filter { $0 == true }
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] _ in
+        dismiss(animated: true)
+      }.store(in: &cancellables)
+
+    screenView
+      .cancelButton
+      .publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in
+        dismiss(animated: true)
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didInput($0)
+      }.store(in: &cancellables)
+
+    screenView
+      .otherInputField
+      .textPublisher
+      .sink { [unowned self] in
+        viewModel.didOtherInput($0)
+      }.store(in: &cancellables)
+
+    screenView
+      .inputField
+      .returnPublisher
+      .sink { [unowned self] in
+        screenView.inputField.endEditing(true)
+      }.store(in: &cancellables)
+
+    screenView
+      .otherInputField
+      .returnPublisher
+      .sink { [unowned self] in
+        screenView.otherInputField.endEditing(true)
+      }.store(in: &cancellables)
+
+    screenView
+      .createButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        viewModel.didTapCreate(groupMembers)
+      }.store(in: &cancellables)
+  }
+}
diff --git a/Sources/CreateGroupFeature/CreateGroupView.swift b/Sources/CreateGroupFeature/CreateGroupView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8d38493433607e66a2ac836e8ae8e07d473be134
--- /dev/null
+++ b/Sources/CreateGroupFeature/CreateGroupView.swift
@@ -0,0 +1,107 @@
+import UIKit
+import Shared
+import InputField
+import AppResources
+
+final class CreateGroupView: UIView {
+  let titleLabel = UILabel()
+  let subtitleView = TextWithInfoView()
+  let inputField = InputField()
+  let otherInputField = InputField()
+  let stackView = UIStackView()
+  let createButton = CapsuleButton()
+  let cancelButton = CapsuleButton()
+
+  var didTapInfo: (() -> Void)?
+
+  init() {
+    super.init(frame: .zero)
+
+    layer.cornerRadius = 40
+    backgroundColor = Asset.neutralWhite.color
+    layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
+
+    titleLabel.textAlignment = .left
+    titleLabel.text = Localized.CreateGroup.Drawer.title
+    titleLabel.font = Fonts.Mulish.bold.font(size: 26.0)
+    titleLabel.textColor = Asset.neutralActive.color
+
+    inputField.setup(
+      style: .regular,
+      title: Localized.CreateGroup.Drawer.input,
+      placeholder: Localized.CreateGroup.Drawer.placeholder,
+      leftView: .image(Asset.personGray.image),
+      accessibility: Localized.Accessibility.CreateGroup.Drawer.input,
+      subtitleColor: Asset.neutralDisabled.color
+    )
+
+    otherInputField.setup(
+      style: .regular,
+      title: Localized.CreateGroup.Drawer.otherInput,
+      placeholder: Localized.CreateGroup.Drawer.otherPlaceholder,
+      leftView: .image(Asset.balloon.image),
+      accessibility: Localized.Accessibility.CreateGroup.Drawer.otherInput,
+      subtitleColor: Asset.neutralDisabled.color
+    )
+
+    createButton.set(
+      style: .brandColored,
+      title: Localized.CreateGroup.Drawer.action,
+      accessibility: Localized.Accessibility.CreateGroup.Drawer.create
+    )
+
+    cancelButton.set(
+      style: .seeThrough,
+      title: Localized.CreateGroup.Drawer.cancel
+    )
+
+    stackView.spacing = 20
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(subtitleView)
+    stackView.addArrangedSubview(inputField)
+    stackView.addArrangedSubview(otherInputField)
+    stackView.addArrangedSubview(createButton)
+    stackView.addArrangedSubview(cancelButton)
+
+    addSubview(stackView)
+
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(60)
+      $0.left.equalToSuperview().offset(50)
+      $0.right.equalToSuperview().offset(-50)
+      $0.bottom.equalToSuperview().offset(-70)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func set(count: Int, didTap: @escaping () -> Void) {
+    self.didTapInfo = didTap
+
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.alignment = .left
+    paragraphStyle.lineHeightMultiple = 1.1
+
+    subtitleView.setup(
+      text: Localized.CreateGroup.Drawer.subtitle("\(count)"),
+      attributes: [
+        .paragraphStyle: paragraphStyle,
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.semiBold.font(size: 14.0) as Any
+      ],
+      didTapInfo: { [weak self] in self?.didTapInfo?() }
+    )
+  }
+
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+
+    switch status {
+    case .valid:
+      createButton.isEnabled = true
+    case .invalid, .unknown:
+      createButton.isEnabled = false
+    }
+  }
+}
diff --git a/Sources/CreateGroupFeature/CreateGroupViewModel.swift b/Sources/CreateGroupFeature/CreateGroupViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f63eccede0feef855c3b973d948627160c6d6f89
--- /dev/null
+++ b/Sources/CreateGroupFeature/CreateGroupViewModel.swift
@@ -0,0 +1,103 @@
+import Shared
+import Combine
+import AppCore
+import XXModels
+import InputField
+import AppResources
+import Dependencies
+
+import Foundation // ?
+
+struct CreateGroupViewModel {
+  struct ViewState {
+    var welcome: String?
+    var groupName: String = ""
+    var status: InputField.ValidationStatus = .unknown(nil)
+    var shouldDismiss: Bool = false
+  }
+
+  @Dependency(\.app.bgQueue) var bgQueue
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.groupManager) var groupManager
+  @Dependency(\.app.hudManager) var hudManager
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+
+  func didInput(_ string: String) {
+    stateSubject.value.groupName = string
+    validate()
+  }
+
+  func didOtherInput(_ string: String) {
+    stateSubject.value.welcome = string
+  }
+
+  func didTapCreate(_ members: [Contact]) {
+    hudManager.show()
+    let welcome = stateSubject.value.welcome
+    let name = stateSubject.value.groupName.trimmingCharacters(in: .whitespacesAndNewlines)
+
+    bgQueue.schedule {
+      do {
+        guard let manager = groupManager.get() else {
+          fatalError("Can't create a group w/out a manager")
+        }
+        let report = try manager.makeGroup(
+          membership: members.map(\.id),
+          message: welcome?.data(using: .utf8),
+          name: name.data(using: .utf8)
+        )
+        let group = Group(
+          id: report.id,
+          name: name,
+          leaderId: try messenger.e2e.get()!.getContact().getId(),
+          createdAt: Date(),
+          authStatus: .participating,
+          serialized: try report.encode()
+        )
+        try dbManager.getDB().saveGroup(group)
+        if let welcome {
+          try dbManager.getDB().saveMessage(.init(
+            senderId: try messenger.e2e.get()!.getContact().getId(),
+            recipientId: nil,
+            groupId: group.id,
+            date: group.createdAt,
+            status: .sent,
+            isUnread: false,
+            text: welcome
+          ))
+        }
+        try members.map {
+          GroupMember(groupId: group.id, contactId: $0.id)
+        }.forEach {
+          try dbManager.getDB().saveGroupMember($0)
+        }
+        _ = try dbManager.getDB().fetchGroupInfos(
+          .init(groupId: group.id)
+        ).first
+        hudManager.hide()
+        stateSubject.value.shouldDismiss = true
+      } catch {
+        hudManager.show(.init(error: error))
+      }
+    }
+  }
+
+  private func validate() {
+    let value = stateSubject.value.groupName.trimmingCharacters(in: .whitespacesAndNewlines)
+    guard value.count >= 4 else {
+      stateSubject.value.status = .invalid(Localized.CreateGroup.Drawer.minimum)
+      return
+    }
+    guard value.count < 21 else {
+      stateSubject.value.status = .invalid(Localized.CreateGroup.Drawer.maximum)
+      return
+    }
+    stateSubject.value.status = .valid(nil)
+  }
+}
diff --git a/Sources/Defaults/Dependencies.swift b/Sources/Defaults/Dependencies.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e0446cf6f3a8c8d952b419df86a95cb7043d52fd
--- /dev/null
+++ b/Sources/Defaults/Dependencies.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum KeyObjectStoreDependencyKey: DependencyKey {
+  static let liveValue: KeyObjectStore = .live
+  static let testValue: KeyObjectStore = .unimplemented
+}
+
+extension DependencyValues {
+  public var store: KeyObjectStore {
+    get { self[KeyObjectStoreDependencyKey.self] }
+    set { self[KeyObjectStoreDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift
index 1072e3c1cca9e9e195e99f892f489d52b4d6150f..290a567e68cb5e72f81ed09f2ada856e1bfe16c3 100644
--- a/Sources/Defaults/KeyObject.swift
+++ b/Sources/Defaults/KeyObject.swift
@@ -1,5 +1,5 @@
-import DI
 import Foundation
+import ComposableArchitecture
 
 public enum Key: String {
   case email
@@ -23,42 +23,12 @@ public enum Key: String {
   case askedDummyTrafficOnce
 }
 
-public struct KeyObjectStore {
-  var objectForKey: (String) -> Any?
-  var setObjectForKey: (Any?, String) -> Void
-  var removeObjectForKey: (String) -> Void
-
-  public init(
-    objectForKey: @escaping (String) -> Any?,
-    setObjectForKey: @escaping (Any?, String) -> Void,
-    removeObjectForKey: @escaping (String) -> Void
-  ) {
-    self.objectForKey = objectForKey
-    self.setObjectForKey = setObjectForKey
-    self.removeObjectForKey = removeObjectForKey
-  }
-}
-
-public extension KeyObjectStore {
-  static func mock(dictionary: NSMutableDictionary) -> Self {
-    Self(objectForKey: { dictionary[$0] },
-         setObjectForKey: { dictionary[$1] = $0 },
-         removeObjectForKey: { dictionary[$0] = nil })
-  }
-
-  static let userDefaults = Self(
-    objectForKey: UserDefaults.standard.object(forKey:),
-    setObjectForKey: UserDefaults.standard.set(_:forKey:),
-    removeObjectForKey: UserDefaults.standard.removeObject(forKey:)
-  )
-}
-
 @propertyWrapper
 public struct KeyObject<T> {
   let key: String
   let defaultValue: T
 
-  @Dependency var store: KeyObjectStore
+  @Dependency(\.store) var store: KeyObjectStore
 
   public init(_ key: Key, defaultValue: T) {
     self.key = key.rawValue
@@ -67,13 +37,13 @@ public struct KeyObject<T> {
 
   public var wrappedValue: T {
     get {
-      store.objectForKey(key) as? T ?? defaultValue
+      store.get(key) as? T ?? defaultValue
     }
     set {
       if let value = newValue as? OptionalProtocol, value.isNil() {
-        store.removeObjectForKey(key)
+        store.remove(key)
       } else {
-        store.setObjectForKey(newValue, key)
+        store.set(newValue, for: key)
       }
     }
   }
diff --git a/Sources/Defaults/KeyObjectStore.swift b/Sources/Defaults/KeyObjectStore.swift
new file mode 100644
index 0000000000000000000000000000000000000000..38588f92da0ba9f28ed3c389afb8f9c9469a049a
--- /dev/null
+++ b/Sources/Defaults/KeyObjectStore.swift
@@ -0,0 +1,21 @@
+public struct KeyObjectStore {
+  public var get: ObjectForKey
+  public var set: SetObjectForKey
+  public var remove: RemoveObjectForKey
+}
+
+extension KeyObjectStore {
+  public static let live = KeyObjectStore(
+    get: .live,
+    set: .live,
+    remove: .live
+  )
+}
+
+extension KeyObjectStore {
+  public static let unimplemented = KeyObjectStore(
+    get: .unimplemented,
+    set: .unimplemented,
+    remove: .unimplemented
+  )
+}
diff --git a/Sources/Defaults/ObjectForKey.swift b/Sources/Defaults/ObjectForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e2c51f0699a95fd32f636dc58d099f2f4afe0c2c
--- /dev/null
+++ b/Sources/Defaults/ObjectForKey.swift
@@ -0,0 +1,22 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct ObjectForKey {
+  public var run: (String) -> Any?
+
+  public func callAsFunction(_ key: String) -> Any? {
+    run(key)
+  }
+}
+
+extension ObjectForKey {
+  public static let live = ObjectForKey {
+    UserDefaults.standard.object(forKey: $0)
+  }
+}
+
+extension ObjectForKey {
+  public static let unimplemented = ObjectForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Defaults/RemoveObjectForKey.swift b/Sources/Defaults/RemoveObjectForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f8108bcffc0d978558f38b017e2cc9f0de848cc3
--- /dev/null
+++ b/Sources/Defaults/RemoveObjectForKey.swift
@@ -0,0 +1,22 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct RemoveObjectForKey {
+  public var run: (String) -> Void
+
+  public func callAsFunction(_ key: String) -> Void {
+    run(key)
+  }
+}
+
+extension RemoveObjectForKey {
+  public static let live = RemoveObjectForKey {
+    UserDefaults.standard.removeObject(forKey: $0)
+  }
+}
+
+extension RemoveObjectForKey {
+  public static let unimplemented = RemoveObjectForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Defaults/SetObjectForKey.swift b/Sources/Defaults/SetObjectForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c2f7d625d607474cdb4f7ba673fe9ead94673651
--- /dev/null
+++ b/Sources/Defaults/SetObjectForKey.swift
@@ -0,0 +1,22 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct SetObjectForKey {
+  public var run: (Any?, String) -> Void
+
+  public func callAsFunction(_ value: Any?, for key: String) -> Void {
+    run(value, key)
+  }
+}
+
+extension SetObjectForKey {
+  public static let live = SetObjectForKey { value, key in
+    UserDefaults.standard.set(value, forKey: key)
+  }
+}
+
+extension SetObjectForKey {
+  public static let unimplemented = SetObjectForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/FetchBannedList/Dependency.swift b/Sources/FetchBannedList/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8eb9ad1696a663a47bcb257e3b71d09fc6225e11
--- /dev/null
+++ b/Sources/FetchBannedList/Dependency.swift
@@ -0,0 +1,14 @@
+import Dependencies
+
+private enum FetchBannedListDependencyKey: DependencyKey {
+  static let liveValue: FetchBannedList = .live
+  static let testValue: FetchBannedList = .unimplemented
+}
+
+extension DependencyValues {
+  public var fetchBannedList: FetchBannedList {
+    get { self[FetchBannedListDependencyKey.self] }
+    set { self[FetchBannedListDependencyKey.self] = newValue }
+  }
+}
+
diff --git a/Sources/FetchBannedList/FetchBannedList.swift b/Sources/FetchBannedList/FetchBannedList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9315cd589c431e3ed010d34e7c321f2dc9c5c787
--- /dev/null
+++ b/Sources/FetchBannedList/FetchBannedList.swift
@@ -0,0 +1,46 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct FetchBannedList {
+  public enum Error: Swift.Error, Equatable {
+    case network(URLError)
+    case invalidResponse
+  }
+
+  public typealias Completion = (Result<Data, Error>) -> Void
+
+  public var run: (@escaping Completion) -> Void
+
+  public func callAsFunction(completion: @escaping Completion) {
+    run(completion)
+  }
+}
+
+extension FetchBannedList {
+  public static let live = FetchBannedList { completion in
+    let url = URL(string: "https://elixxir-bins.s3.us-west-1.amazonaws.com/client/bannedUsers/banned.csv")!
+    let session = URLSession.shared
+    let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
+    let task = session.dataTask(with: request) { data, response, error in
+      if let error = error {
+        completion(.failure(.network(error as! URLError)))
+        return
+      }
+      guard let response = response as? HTTPURLResponse,
+            (200..<300).contains(response.statusCode),
+            let data = data
+      else {
+        completion(.failure(.invalidResponse))
+        return
+      }
+      completion(.success(data))
+    }
+    task.resume()
+  }
+}
+
+extension FetchBannedList {
+  public static let unimplemented = FetchBannedList(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/GroupDraftFeature/GroupDraftCollectionCell.swift b/Sources/GroupDraftFeature/GroupDraftCollectionCell.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cdcb1393c7460df0410e352ca7ab3347d359dbaf
--- /dev/null
+++ b/Sources/GroupDraftFeature/GroupDraftCollectionCell.swift
@@ -0,0 +1,83 @@
+import UIKit
+import Shared
+import Combine
+import AppResources
+
+final class GroupDraftCollectionCell: UICollectionViewCell {
+  let titleLabel = UILabel()
+  let removeButton = UIButton()
+  let upperView = UIView()
+  let avatarView = AvatarView()
+  
+  var didTapRemove: (() -> Void)?
+  var cancellables = Set<AnyCancellable>()
+  
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    
+    titleLabel.numberOfLines = 2
+    titleLabel.lineBreakMode = .byWordWrapping
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralDark.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    
+    removeButton.layer.cornerRadius = 9
+    removeButton.backgroundColor = Asset.accentDanger.color
+    removeButton.setImage(Asset.contactListAvatarRemove.image, for: .normal)
+    
+    upperView.addSubview(avatarView)
+    contentView.addSubview(titleLabel)
+    contentView.addSubview(upperView)
+    contentView.addSubview(removeButton)
+    
+    upperView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+    }
+    
+    avatarView.snp.makeConstraints {
+      $0.width.equalTo(48)
+      $0.height.equalTo(48)
+      $0.top.equalToSuperview().offset(4)
+      $0.left.equalToSuperview().offset(4)
+      $0.right.equalToSuperview().offset(-4)
+      $0.bottom.equalToSuperview().offset(-4)
+    }
+    
+    removeButton.snp.makeConstraints {
+      $0.centerY.equalTo(avatarView.snp.top).offset(5)
+      $0.centerX.equalTo(avatarView.snp.right).offset(-5)
+      $0.width.equalTo(18)
+      $0.height.equalTo(18)
+    }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(upperView.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    titleLabel.text = nil
+    avatarView.prepareForReuse()
+    cancellables.removeAll()
+  }
+  
+  func setup(title: String, image: Data?) {
+    titleLabel.text = title
+    avatarView.setupProfile(title: title, image: image, size: .large)
+    cancellables.removeAll()
+    
+    removeButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        didTapRemove?()
+      }.store(in: &cancellables)
+  }
+}
diff --git a/Sources/ContactListFeature/Controllers/CreateGroupController.swift b/Sources/GroupDraftFeature/GroupDraftController.swift
similarity index 88%
rename from Sources/ContactListFeature/Controllers/CreateGroupController.swift
rename to Sources/GroupDraftFeature/GroupDraftController.swift
index 34539b857c33cec6bbf1ba0a074db9f228493e48..27dd858fa3abc733e288f4495d53f0aaad629741 100644
--- a/Sources/ContactListFeature/Controllers/CreateGroupController.swift
+++ b/Sources/GroupDraftFeature/GroupDraftController.swift
@@ -2,20 +2,21 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import Navigation
-import DI
+import AppResources
+import Dependencies
+import AppNavigation
 
-public final class CreateGroupController: UIViewController {
-  @Dependency var navigator: Navigator
+public final class GroupDraftController: UIViewController {
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var titleLabel = UILabel()
   private lazy var createButton = UIButton()
-  private lazy var screenView = CreateGroupView()
+  private lazy var screenView = GroupDraftView()
 
   private var selectedElements = [Contact]() {
     didSet { screenView.tableView.reloadData() }
   }
-  private let viewModel = CreateGroupViewModel()
+  private let viewModel = GroupDraftViewModel()
   private var cancellables = Set<AnyCancellable>()
   private var tableDataSource: UITableViewDiffableDataSource<SectionId, Contact>!
   private var collectionDataSource: UICollectionViewDiffableDataSource<SectionId, Contact>!
@@ -72,12 +73,12 @@ public final class CreateGroupController: UIViewController {
   private func setupTableAndCollection() {
     screenView.tableView.rowHeight = 64.0
     screenView.tableView.register(AvatarCell.self)
-    screenView.collectionView.register(CreateGroupCollectionCell.self)
+    screenView.collectionView.register(GroupDraftCollectionCell.self)
 
     collectionDataSource = UICollectionViewDiffableDataSource<SectionId, Contact>(
       collectionView: screenView.collectionView
     ) { [weak viewModel] collectionView, indexPath, contact in
-      let cell: CreateGroupCollectionCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
+      let cell: GroupDraftCollectionCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
 
       let title = (contact.nickname ?? contact.username) ?? ""
       cell.setup(title: title, image: contact.photo)
@@ -167,21 +168,15 @@ public final class CreateGroupController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-//        coordinator.toGroupDrawer(
-//          with: count,
-//          from: self, { (name, welcome) in
-//            self.viewModel.create(
-//              name: name,
-//              welcome: welcome,
-//              members: self.selectedElements
-//            )
-//          }
-//        )
+        navigator.perform(PresentCreateGroup(
+          members: selectedElements,
+          from: self
+        ))
       }.store(in: &cancellables)
   }
 }
 
-extension CreateGroupController: UITableViewDelegate {
+extension GroupDraftController: UITableViewDelegate {
   public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     if let contact = tableDataSource.itemIdentifier(for: indexPath) {
       viewModel.didSelect(contact: contact)
diff --git a/Sources/GroupDraftFeature/GroupDraftView.swift b/Sources/GroupDraftFeature/GroupDraftView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..972cd50602ddac171f203a01b4fef82d04ab8a37
--- /dev/null
+++ b/Sources/GroupDraftFeature/GroupDraftView.swift
@@ -0,0 +1,65 @@
+import UIKit
+import Shared
+import SnapKit
+import AppResources
+
+final class GroupDraftView: UIView {
+  let stackView = UIStackView()
+  let tableView = UITableView()
+  let searchComponent = SearchComponent()
+  lazy var collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+  
+  let layout: UICollectionViewFlowLayout = {
+    let layout = UICollectionViewFlowLayout()
+    layout.minimumInteritemSpacing = 45
+    layout.itemSize = CGSize(width: 56, height: 100)
+    layout.scrollDirection = .horizontal
+    return layout
+  }()
+  
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    
+    tableView.separatorStyle = .none
+    tableView.tintColor = Asset.brandPrimary.color
+    tableView.backgroundColor = Asset.neutralWhite.color
+    tableView.allowsMultipleSelectionDuringEditing = true
+    tableView.setEditing(true, animated: true)
+    
+    searchComponent.set(
+      placeholder: "Search connections",
+      imageAtRight: UIImage.color(.clear)
+    )
+    
+    collectionView.backgroundColor = Asset.neutralWhite.color
+    collectionView.contentInset = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 30)
+    
+    stackView.spacing = 31
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(collectionView)
+    stackView.addArrangedSubview(tableView)
+    
+    addSubview(stackView)
+    addSubview(searchComponent)
+    
+    searchComponent.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(20)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+    }
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(searchComponent.snp.bottom).offset(20)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+    
+    collectionView.snp.makeConstraints {
+      $0.height.equalTo(100)
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+}
diff --git a/Sources/GroupDraftFeature/GroupDraftViewModel.swift b/Sources/GroupDraftFeature/GroupDraftViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..476dd69ad26eaab2de5a17ed501289f830799374
--- /dev/null
+++ b/Sources/GroupDraftFeature/GroupDraftViewModel.swift
@@ -0,0 +1,76 @@
+import Combine
+import AppCore
+import XXModels
+import Defaults
+import Foundation
+import Dependencies
+import ReportingFeature
+
+final class GroupDraftViewModel {
+  @Dependency(\.app.bgQueue) var bgQueue
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.reportingStatus) var reportingStatus
+
+  @KeyObject(.username, defaultValue: "") var username: String
+
+  var myId: Data {
+    try! messenger.e2e.get()!.getContact().getId()
+  }
+
+  var selected: AnyPublisher<[XXModels.Contact], Never> {
+    selectedContactsRelay.eraseToAnyPublisher()
+  }
+
+  var contacts: AnyPublisher<[XXModels.Contact], Never> {
+    contactsRelay.eraseToAnyPublisher()
+  }
+
+  var info: AnyPublisher<GroupInfo, Never> {
+    infoRelay.eraseToAnyPublisher()
+  }
+
+  private var allContacts = [XXModels.Contact]()
+  private var cancellables = Set<AnyCancellable>()
+  private let infoRelay = PassthroughSubject<GroupInfo, Never>()
+  private let contactsRelay = CurrentValueSubject<[XXModels.Contact], Never>([])
+  private let selectedContactsRelay = CurrentValueSubject<[XXModels.Contact], Never>([])
+
+  init() {
+    let query = Contact.Query(
+      authStatus: [.friend],
+      isBlocked: reportingStatus.isEnabled() ? false : nil,
+      isBanned: reportingStatus.isEnabled() ? false : nil
+    )
+
+    try! dbManager.getDB().fetchContactsPublisher(query)
+      .replaceError(with: [])
+      .map { $0.filter { $0.id != self.myId }}
+      .map { $0.sorted(by: { $0.username! < $1.username! })}
+      .sink { [unowned self] in
+        allContacts = $0
+        contactsRelay.send($0)
+      }.store(in: &cancellables)
+  }
+
+  func didSelect(contact: XXModels.Contact) {
+    if selectedContactsRelay.value.contains(contact) {
+      selectedContactsRelay.value.removeAll { $0.username == contact.username }
+    } else {
+      selectedContactsRelay.value.append(contact)
+    }
+  }
+
+  func filter(_ text: String) {
+    guard text.isEmpty == false else {
+      contactsRelay.send(allContacts)
+      return
+    }
+
+    contactsRelay.send(
+      allContacts.filter {
+        ($0.username ?? "").contains(text.lowercased())
+      }
+    )
+  }
+}
diff --git a/Sources/Keychain/Dependency.swift b/Sources/Keychain/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..02ca45a9267826025a38dc77c4826eb034113bb1
--- /dev/null
+++ b/Sources/Keychain/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum KeychainDependencyKey: DependencyKey {
+  static let liveValue: KeychainManager = .live
+  static let testValue: KeychainManager = .unimplemented
+}
+
+extension DependencyValues {
+  public var keychain: KeychainManager {
+    get { self[KeychainDependencyKey.self] }
+    set { self[KeychainDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/Keychain/DestroyKeychain.swift b/Sources/Keychain/DestroyKeychain.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8bb24fe094745fa5b65e2c3e9e68b6cfc2fabc08
--- /dev/null
+++ b/Sources/Keychain/DestroyKeychain.swift
@@ -0,0 +1,22 @@
+import KeychainAccess
+import XCTestDynamicOverlay
+
+public struct DestroyKeychain {
+  public var run: () throws -> Void
+
+  public func callAsFunction() throws -> Void {
+    try run()
+  }
+}
+
+extension DestroyKeychain {
+  public static let live = DestroyKeychain {
+    try Keychain(service: "XXM").removeAll()
+  }
+}
+
+extension DestroyKeychain {
+  public static let unimplemented = DestroyKeychain(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Keychain/GetValueForKey.swift b/Sources/Keychain/GetValueForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..31fe3ca81fc53279bf5f1d0a99ca10704927839e
--- /dev/null
+++ b/Sources/Keychain/GetValueForKey.swift
@@ -0,0 +1,22 @@
+import KeychainAccess
+import XCTestDynamicOverlay
+
+public struct GetValueForKey {
+  public var run: (String) throws -> String?
+
+  public func callAsFunction(_ key: String) throws -> String? {
+    try run(key)
+  }
+}
+
+extension GetValueForKey {
+  public static let live = GetValueForKey {
+    try Keychain(service: "XXM").get($0)
+  }
+}
+
+extension GetValueForKey {
+  public static let unimplemented = GetValueForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Keychain/KeychainHandler.swift b/Sources/Keychain/KeychainHandler.swift
index 3ed93be94118e9ec41f2ab86d80cf177d7fe0225..6b55051142ba5937692e491e1620460469cf0b6e 100644
--- a/Sources/Keychain/KeychainHandler.swift
+++ b/Sources/Keychain/KeychainHandler.swift
@@ -1,51 +1,24 @@
-import Foundation
-import KeychainAccess
-
-public enum KeychainSFTP: String {
-  case pwd
-  case host
-  case username
+public struct KeychainManager {
+  public var set: SetValueForKey
+  public var get: GetValueForKey
+  public var remove: RemoveValueForKey
+  public var destroy: DestroyKeychain
 }
 
-public protocol KeychainHandling {
-  func clear() throws
-  func getPassword() throws -> Data?
-  func remove(_ key: String) throws
-  func store(password pwd: Data) throws
-
-  func get(key: KeychainSFTP) throws -> String?
-  func store(key: KeychainSFTP, value: String) throws
+extension KeychainManager {
+  public static let live = KeychainManager(
+    set: .live,
+    get: .live,
+    remove: .live,
+    destroy: .live
+  )
 }
 
-public struct KeychainHandler: KeychainHandling {
-  private let keychain: Keychain
-  private let password = "password"
-
-  public init() {
-    self.keychain = Keychain(service: "XXM")
-  }
-
-  public func remove(_ key: String) throws {
-    try keychain.remove(key)
-  }
-
-  public func clear() throws {
-    try keychain.removeAll()
-  }
-
-  public func store(password pwd: Data) throws {
-    try keychain.set(pwd, key: password)
-  }
-
-  public func getPassword() throws -> Data? {
-    try keychain.getData(password)
-  }
-
-  public func get(key: KeychainSFTP) throws -> String? {
-    try keychain.get(key.rawValue)
-  }
-
-  public func store(key: KeychainSFTP, value: String) throws {
-    try keychain.set(value, key: key.rawValue)
-  }
+extension KeychainManager {
+  public static let unimplemented = KeychainManager(
+    set: .unimplemented,
+    get: .unimplemented,
+    remove: .unimplemented,
+    destroy: .unimplemented
+  )
 }
diff --git a/Sources/Keychain/MockKeychainHandler.swift b/Sources/Keychain/MockKeychainHandler.swift
deleted file mode 100644
index ea2af5d6467860b5c13d79f01dbdf223862115e1..0000000000000000000000000000000000000000
--- a/Sources/Keychain/MockKeychainHandler.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-import Foundation
-
-public struct MockKeychainHandler: KeychainHandling {
-    public init() {}
-
-    public func clear() throws {}
-    public func remove(_ key: String) throws {}
-    public func store(password pwd: Data) throws {}
-    public func getPassword() throws -> Data? { Data() }
-    public func get(key: KeychainSFTP) throws -> String? { nil }
-    public func store(key: KeychainSFTP, value: String) throws {}
-}
diff --git a/Sources/Keychain/RemoveValueForKey.swift b/Sources/Keychain/RemoveValueForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9868a6f6d6bed828d64881877a8d082a90d8afe1
--- /dev/null
+++ b/Sources/Keychain/RemoveValueForKey.swift
@@ -0,0 +1,22 @@
+import KeychainAccess
+import XCTestDynamicOverlay
+
+public struct RemoveValueForKey {
+  public var run: (String) throws -> Void
+
+  public func callAsFunction(_ key: String) throws -> Void {
+    try run(key)
+  }
+}
+
+extension RemoveValueForKey {
+  public static let live = RemoveValueForKey {
+    try Keychain(service: "XXM").remove($0)
+  }
+}
+
+extension RemoveValueForKey {
+  public static let unimplemented = RemoveValueForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Keychain/SetValueForKey.swift b/Sources/Keychain/SetValueForKey.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c0cc66ba4816f3156798705ef2bfc34275698a58
--- /dev/null
+++ b/Sources/Keychain/SetValueForKey.swift
@@ -0,0 +1,22 @@
+import KeychainAccess
+import XCTestDynamicOverlay
+
+public struct SetValueForKey {
+  public var run: (String, String) throws -> Void
+
+  public func callAsFunction(_ value: String, for key: String) throws -> Void {
+    try run(value, key)
+  }
+}
+
+extension SetValueForKey {
+  public static let live = SetValueForKey { value, key in
+    try Keychain(service: "XXM").set(value, key: key)
+  }
+}
+
+extension SetValueForKey {
+  public static let unimplemented = SetValueForKey(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/LaunchFeature/BackendVersionInformation.swift b/Sources/LaunchFeature/BackendVersionInformation.swift
deleted file mode 100644
index bb52e089d69a5bdc73672d70b936d0afe941c341..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/BackendVersionInformation.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-struct BackendVersionInformation: Codable {
-  var info: DappVersionInformation
-
-  private enum CodingKeys: String, CodingKey {
-    case info = "dapp-id"
-  }
-}
diff --git a/Sources/LaunchFeature/DappVersionInformation.swift b/Sources/LaunchFeature/DappVersionInformation.swift
deleted file mode 100644
index c6d49f32bf3f211ea669cf003a9cc663c86adc76..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/DappVersionInformation.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-public struct DappVersionInformation: Codable {
-  public var appUrl: String
-  public var minimum: String
-  public var isRequired: Bool?
-  public var recommended: String
-  public var minimumMessage: String
-
-  private enum CodingKeys: String, CodingKey {
-    case appUrl = "new_ios_app_url"
-    case minimum = "new_ios_min_version"
-    case recommended = "new_ios_recommended_version"
-    case minimumMessage = "new_minimum_popup_msg"
-  }
-}
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index dbc4067bbfbdfeb388cf52a84b05eff5c24ff01e..9371455d9dc07804847e6642d731cccb3d452ec8 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -1,51 +1,24 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
 import PushFeature
-import DrawerFeature
+import Dependencies
 import AppResources
-import ComposableArchitecture
+import DrawerFeature
+import AppNavigation
 
 public final class LaunchController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = LaunchView()
-
   private let viewModel = LaunchViewModel()
-  public var pendingPushRoute: PushRouter.Route?
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
 
-  public override func viewDidAppear(_ animated: Bool) {
-    super.viewDidAppear(animated)
-    viewModel.viewDidAppear()
-  }
-
   public override func loadView() {
     view = screenView
   }
 
-  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.frame = screenView.bounds
-    gradient.startPoint = CGPoint(x: 1, y: 0)
-    gradient.endPoint = CGPoint(x: 0, y: 1)
-    screenView.layer.insertSublayer(gradient, at: 0)
-  }
-
   public override func viewDidLoad() {
     super.viewDidLoad()
 
@@ -58,10 +31,10 @@ public final class LaunchController: UIViewController {
             navigator.perform(PresentTermsAndConditions(replacing: true, on: navigationController!))
             return
           }
-          if let route = pendingPushRoute {
-            hasPendingPushRoute(route)
-            return
-          }
+//          if let route = pendingPushRoute {
+//            hasPendingPushRoute(route)
+//            return
+//          }
           navigator.perform(PresentChatList(on: navigationController!))
           return
         }
@@ -73,6 +46,8 @@ public final class LaunchController: UIViewController {
           offerUpdate(model: update)
         }
       }.store(in: &cancellables)
+
+    viewModel.startLaunch()
   }
 
   private func hasPendingPushRoute(_ route: PushRouter.Route) {
diff --git a/Sources/LaunchFeature/LaunchView.swift b/Sources/LaunchFeature/LaunchView.swift
index b1c3982f558dc0b79c2e369c68f1e5b79f442723..40f6fb44b8b23520c062774adca2df350b98a409 100644
--- a/Sources/LaunchFeature/LaunchView.swift
+++ b/Sources/LaunchFeature/LaunchView.swift
@@ -1,16 +1,28 @@
 import UIKit
-import Shared
 import AppResources
 
 final class LaunchView: UIView {
   let imageView = UIImageView()
+  let gradientLayer = CAGradientLayer()
 
   init() {
     super.init(frame: .zero)
+
+    gradientLayer.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
+    ]
+    gradientLayer.startPoint = CGPoint(x: 1, y: 0)
+    gradientLayer.endPoint = CGPoint(x: 0, y: 1)
+    layer.insertSublayer(gradientLayer, at: 0)
     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)
@@ -18,4 +30,8 @@ final class LaunchView: UIView {
   }
 
   required init?(coder: NSCoder) { nil }
+
+  override func layoutSubviews() {
+    gradientLayer.frame = bounds
+  }
 }
diff --git a/Sources/LaunchFeature/LaunchViewModel+Banned.swift b/Sources/LaunchFeature/LaunchViewModel+Banned.swift
deleted file mode 100644
index 1449fb675e7e190cc257785b55f43517f39ac518..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/LaunchViewModel+Banned.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-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
deleted file mode 100644
index 15ae6c42c88abf3f095c05d666720761707ffd22..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/LaunchViewModel+Database.swift
+++ /dev/null
@@ -1,74 +0,0 @@
-import XXModels
-import Foundation
-import XXDatabase
-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"))
-    }
-
-    DI.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? DI.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? DI.Container.shared.resolve(),
-          let info = try? database.fetchGroupInfos(query).first else {
-      return nil
-    }
-
-    return info
-  }
-}
diff --git a/Sources/LaunchFeature/LaunchViewModel+Errors.swift b/Sources/LaunchFeature/LaunchViewModel+Errors.swift
deleted file mode 100644
index 399667657243523475a2857e9838451a0198d587..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/LaunchViewModel+Errors.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-import XXClient
-import Foundation
-
-extension LaunchViewModel {
-  func updateErrors(
-    completion: @escaping (Result<Void, Error>) -> Void
-  ) {
-    let url = "https://git.xx.network/elixxir/client-error-database/-/raw/main/clientErrors.json"
-    downloadErrors(from: url) {
-      switch $0 {
-      case .success(let string):
-        do {
-          try UpdateCommonErrors.live(jsonFile: string)
-          completion(.success(()))
-        } catch {
-          completion(.failure(error))
-        }
-      case .failure(let error):
-        completion(.failure(error))
-      }
-    }
-  }
-
-  func downloadErrors(
-    from urlString: String,
-    completion: @escaping (Result<String, Error>) -> Void
-  ) {
-    URLSession.shared.dataTask(with: URL(string: urlString)!) { data, _, error in
-      if let error {
-        completion(.failure(error))
-        return
-      }
-      guard let data else {
-        fatalError("No errors or data when downloading \(urlString)")
-      }
-      guard let string = String(data: data, encoding: .utf8) else {
-        fatalError("Impossible to decode error json")
-      }
-      completion(.success(string))
-    }.resume()
-  }
-}
diff --git a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
deleted file mode 100644
index abf90591ceb280b045fb00babcbc65ee111337a9..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
+++ /dev/null
@@ -1,431 +0,0 @@
-import Shared
-import XXClient
-import XXModels
-import Foundation
-import XXMessengerClient
-
-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(.error)
-    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 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 DI.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
-        }
-      })
-    )
-
-    DI.Container.shared.register(manager)
-  }
-
-  func generateTrafficManager() throws {
-    let manager = try NewDummyTrafficManager.live(
-      cMixId: messenger.e2e()!.getId()
-    )
-
-    DI.Container.shared.register(manager)
-    try! manager.setStatus(dummyTrafficOn)
-  }
-
-  func setupMessenger() throws {
-    setupLogWriter()
-    setupAuthCallback()
-    setupBackupCallback()
-    setupMessageCallback()
-
-    if messenger.isLoaded() == false {
-      if messenger.isCreated() == false {
-        try messenger.create()
-      }
-
-      try messenger.load()
-    }
-
-    try messenger.start()
-
-    if messenger.isConnected() == false {
-      try messenger.connect()
-      try messenger.listenForMessages()
-    }
-
-    try generateGroupManager()
-    try generateTrafficManager()
-    listenToNetworkUpdates()
-
-    if messenger.isLoggedIn() == false {
-      if try messenger.isRegistered() {
-        try messenger.logIn()
-        hudController.dismiss()
-        stateSubject.value.shouldPushChats = true
-      } else {
-        try? sftpManager.unlink()
-        try? dropboxManager.unlink()
-        hudController.dismiss()
-        stateSubject.value.shouldPushOnboarding = true
-      }
-    } else {
-      hudController.dismiss()
-      stateSubject.value.shouldPushChats = true
-    }
-    if !messenger.isBackupRunning() {
-      try? messenger.resumeBackup()
-    }
-
-    try messenger.trackServices {
-      print(">>> Error on track services callback: \($0.localizedDescription)")
-    }
-
-    // TODO: Biometric auth
-  }
-}
-
-
-//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? DI.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(DI.Container.shared.dependencies)
-//    }
-//  }
-//}
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 3bd27c5e7669f6f9bf98e6c11ab25cddfb870b85..82798860455c662ca9e773e4dc2ea641852a3a08 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -5,15 +5,25 @@ import XXModels
 import Keychain
 import XXClient
 import CloudFiles
-import Foundation
-import Permissions
+import CheckVersion
+import AppResources
 import BackupFeature
-import VersionChecking
 import ReportingFeature
-import CombineSchedulers
 import CloudFilesDropbox
 import XXMessengerClient
 
+import UpdateErrors
+import FetchBannedList
+import ProcessBannedList
+
+import AppCore
+import Foundation
+import PermissionsFeature
+import ComposableArchitecture
+
+import XXDatabase
+import XXLegacyDatabaseMigrator
+
 import class XXClient.Cancellable
 
 final class LaunchViewModel {
@@ -32,37 +42,43 @@ final class LaunchViewModel {
     var shouldPushOnboarding = false
   }
 
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var versionCheck: VersionCheck
-  @Dependency var hudController: HUDController
-  @Dependency var backupService: BackupService
-  @Dependency var fetchBannedList: FetchBannedList
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var toastController: ToastController
-  @Dependency var keychainHandler: KeychainHandling
-  @Dependency var networkMonitor: NetworkMonitoring
-  @Dependency var processBannedList: ProcessBannedList
-  @Dependency var permissionHandler: PermissionHandling
+  @Dependency(\.app.bgQueue) var bgQueue
+  @Dependency(\.permissions) var permissions
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.keychain) var keychainManager
+  @Dependency(\.updateErrors) var updateErrors
+  @Dependency(\.groupManager) var groupManager
+  @Dependency(\.app.hudManager) var hudManager
+  @Dependency(\.checkVersion) var checkVersion
+  @Dependency(\.dummyTraffic) var dummyTraffic
+  @Dependency(\.backupService) var backupService
+  @Dependency(\.app.toastManager) var toastManager
+  @Dependency(\.fetchBannedList) var fetchBannedList
+  @Dependency(\.reportingStatus) var reportingStatus
+  @Dependency(\.app.networkMonitor) var networkMonitor
+  @Dependency(\.processBannedList) var processBannedList
+
+  @Dependency(\.app.authHandler) var authHandler
+  @Dependency(\.app.backupHandler) var backupHandler
+  @Dependency(\.app.messageListener) var messageListener
+  @Dependency(\.app.receiveFileHandler) var receiveFileHandler
+
+  var authHandlerCancellable: Cancellable?
+  var backupHandlerCancellable: Cancellable?
+  var networkHandlerCancellable: Cancellable?
+  var receiveFileHandlerCancellable: Cancellable?
+  var messageListenerHandlerCancellable: Cancellable?
 
   @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?
-  var backupCallbackCancellable: Cancellable?
-  var networkCallbacksCancellable: Cancellable?
-  var messageListenerCallbacksCancellable: Cancellable?
-
   var statePublisher: AnyPublisher<ViewState, Never> {
     stateSubject.eraseToAnyPublisher()
   }
 
-  private var scheduler: AnySchedulerOf<DispatchQueue> = {
-    DispatchQueue.global().eraseToAnyScheduler()
-  }()
-
   let dropboxManager = CloudFilesManager.dropbox(
     appKey: "ppx0de5f16p9aq2",
     path: "/backup/backup.xxm"
@@ -77,92 +93,209 @@ final class LaunchViewModel {
 
   let stateSubject = CurrentValueSubject <ViewState, Never>(.init())
 
-  func viewDidAppear() {
-    scheduler.schedule(after: .init(.now() + 1)) { [weak self] in
-      guard let self else { return }
-      self.startLaunch()
-    }
-  }
-
-  private func startLaunch() {
+  func startLaunch() {
     if !didAcceptTerms {
       stateSubject.value.shouldShowTerms = true
     }
-    hudController.show()
-    versionCheck.verify { [weak self] in
-      guard let self else { return }
+    hudManager.show()
+    checkVersion {
       switch $0 {
-      case .upToDate:
-        self.didVerifyVersion()
+      case .success(let result):
+        switch result {
+        case .updated:
+          self.didVerifyVersion()
+        case .outdated(let appUrl):
+          self.hudManager.hide()
+
+          self.stateSubject.value.shouldOfferUpdate = .init(
+            content: Localized.Launch.Version.Recommended.title,
+            urlString: appUrl,
+            positiveActionTitle: Localized.Launch.Version.Recommended.positive,
+            negativeActionTitle: Localized.Launch.Version.Recommended.negative,
+            actionStyle: .simplestColoredRed
+          )
+        case .wayTooOld(let appUrl, let minimumVersionMessage):
+          self.hudManager.hide()
+
+          self.stateSubject.value.shouldOfferUpdate = .init(
+            content: minimumVersionMessage,
+            urlString: appUrl,
+            positiveActionTitle: Localized.Launch.Version.Required.positive,
+            negativeActionTitle: nil,
+            actionStyle: .brandColored
+          )
+        }
       case .failure(let error):
-        self.hudController.show(.init(
+        self.hudManager.show(.init(
           title: Localized.Launch.Version.failed,
           content: error.localizedDescription
         ))
-      case .outdated(let info):
-        self.hudController.dismiss()
-        let isRequired = info.isRequired ?? false
-
-        let content = isRequired ?
-        info.minimumMessage :
-        Localized.Launch.Version.Recommended.title
-
-        let positiveActionTitle = isRequired ?
-        Localized.Launch.Version.Required.positive :
-        Localized.Launch.Version.Recommended.positive
-
-        self.stateSubject.value.shouldOfferUpdate = .init(
-          content: content,
-          urlString: info.appUrl,
-          positiveActionTitle: positiveActionTitle,
-          negativeActionTitle: isRequired ? nil : Localized.Launch.Version.Recommended.negative,
-          actionStyle: isRequired ? .brandColored : .simplestColoredRed
-        )
       }
     }
   }
 
   func didRefuseUpdating() {
-    hudController.show()
+    hudManager.show()
     didVerifyVersion()
   }
 
   private func didVerifyVersion() {
-    updateBannedList { [weak self] in
-      guard let self else { return }
+    updateBannedList {
       self.updateErrors {
         switch $0 {
         case .success:
-          self.didFinishAsyncWork()
+          do {
+            if !self.dbManager.hasDB() {
+              try self.dbManager.makeDB()
+            }
+            try self.setupMessenger()
+          } catch {
+            let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+            self.hudManager.show(.init(content: xxError))
+          }
         case .failure(let error):
-          self.hudController.show(.init(error: error))
+          self.hudManager.show(.init(error: error))
         }
       }
     }
   }
+}
+
+extension LaunchViewModel {
+  func setupMessenger() throws {
+    authHandlerCancellable = authHandler {
+      print("\($0.localizedDescription)")
+    }
+    backupHandlerCancellable = backupHandler {
+      print("\($0.localizedDescription)")
+    }
+    receiveFileHandlerCancellable = receiveFileHandler {
+      print("\($0.localizedDescription)")
+    }
+    messageListenerHandlerCancellable = messageListener {
+      print("\($0.localizedDescription)")
+    }
+
+    if messenger.isLoaded() == false {
+      if messenger.isCreated() == false {
+        try messenger.create()
+      }
+      try messenger.load()
+    }
+    try messenger.start()
+    if messenger.isConnected() == false {
+      try messenger.connect()
+      try messenger.listenForMessages()
+    }
+
+    let dummyTrafficManager = try NewDummyTrafficManager.live(
+      cMixId: messenger.e2e()!.getId()
+    )
+    dummyTraffic.set(dummyTrafficManager)
 
-  private func didFinishAsyncWork() {
-    do {
-      try setupDatabase()
-      try setupMessenger()
-    } catch {
-      let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-      hudController.show(.init(content: xxError))
+    try dummyTrafficManager.setStatus(dummyTrafficOn)
+
+    if messenger.isLoggedIn() == false {
+      if try messenger.isRegistered() {
+        try messenger.logIn()
+        hudManager.hide()
+        stateSubject.value.shouldPushChats = true
+      } else {
+        try? sftpManager.unlink()
+        try? dropboxManager.unlink()
+        hudManager.hide()
+        stateSubject.value.shouldPushOnboarding = true
+      }
+    } else {
+      hudManager.hide()
+      stateSubject.value.shouldPushChats = true
+    }
+    if !messenger.isBackupRunning() {
+      try? messenger.resumeBackup()
+    }
+
+    try generateGroupManager()
+
+    try messenger.trackServices {
+      print("\($0.localizedDescription)")
     }
+
+    try messenger.startFileTransfer()
+
+    networkMonitor.start()
+    networkHandlerCancellable = messenger.cMix.get()!.addHealthCallback(
+      HealthCallback {
+        self.networkMonitor.update($0)
+      }
+    )
   }
+}
 
-  private func checkBiometrics(completion: @escaping (Result<Bool, Error>) -> Void) {
-    if permissionHandler.isBiometricsAvailable && isBiometricsOn {
-      permissionHandler.requestBiometrics {
-        switch $0 {
-        case .success(let granted):
-          completion(.success(granted))
-        case .failure(let error):
-          completion(.failure(error))
+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)
       }
-    } else {
-      completion(.success(true))
     }
   }
+
+  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! dbManager.getDB().fetchContacts(query).first {
+            if contact.isBanned == false {
+              contact.isBanned = true
+              try! dbManager.getDB().saveContact(contact)
+              enqueueBanWarning(contact: contact)
+            }
+          } else {
+            try! dbManager.getDB().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"
+    toastManager.enqueue(.init(
+      title: "\(name) has been banned for offensive content.",
+      leftImage: Asset.requestSentToaster.image
+    ))
+  }
+
+  func getContactWith(userId: Data) -> XXModels.Contact? {
+    try? dbManager.getDB().fetchContacts(.init(
+      id: [userId],
+      isBlocked: reportingStatus.isEnabled() ? false : nil,
+      isBanned: reportingStatus.isEnabled() ? false : nil
+    )).first
+  }
+
+  func getGroupInfoWith(groupId: Data) -> GroupInfo? {
+    try? dbManager.getDB().fetchGroupInfos(.init(groupId: groupId)).first
+  }
 }
diff --git a/Sources/LaunchFeature/VersionChecking.swift b/Sources/LaunchFeature/VersionChecking.swift
deleted file mode 100644
index 5dce368728baf174cf24c92b88189cc4b2b7ee0f..0000000000000000000000000000000000000000
--- a/Sources/LaunchFeature/VersionChecking.swift
+++ /dev/null
@@ -1,49 +0,0 @@
-import Combine
-import Foundation
-
-public typealias VersionCompletion = (VersionCheck.Requirement) -> Void
-
-public struct VersionCheck {
-  public enum Requirement {
-    case upToDate
-    case failure(Error)
-    case outdated(DappVersionInformation)
-  }
-
-  public var verify: (@escaping VersionCompletion) -> Void
-}
-
-public extension VersionCheck {
-  static let unimplemented: Self = .init(verify: { _ in fatalError() })
-
-  static let mock: Self = .init { $0(.upToDate) }
-
-  static let live: Self = .init { completion in
-    let request = URLRequest(
-      url: URL(string: "https://elixxir-bins.s3-us-west-1.amazonaws.com/client/dapps/appdb.json")!,
-      cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
-      timeoutInterval: 5
-    )
-    URLSession.shared.dataTask(with: request) { data, _, error in
-      if let error {
-        completion(.failure(error))
-        return
-      }
-      guard let data else {
-        fatalError("No data for version checking")
-      }
-      guard var model = try? JSONDecoder().decode(BackendVersionInformation.self, from: data) else {
-        fatalError()
-      }
-      let bundleVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
-      if bundleVersion >= model.info.recommended {
-        completion(.upToDate)
-      } else {
-        if bundleVersion < model.info.minimum {
-          model.info.isRequired = true
-        }
-        completion(.outdated(model.info))
-      }
-    }.resume()
-  }
-}
diff --git a/Sources/LaunchFeature/ViewModel+GroupManager.swift b/Sources/LaunchFeature/ViewModel+GroupManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c0bef6c8933501f14705df1a1022aaed2ca643e8
--- /dev/null
+++ b/Sources/LaunchFeature/ViewModel+GroupManager.swift
@@ -0,0 +1,192 @@
+import Shared
+import AppCore
+import XXModels
+import XXClient
+import Foundation
+import XXMessengerClient
+
+extension LaunchViewModel {
+  func generateGroupManager() throws {
+    groupManager.set(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: { [weak self] result in
+        guard let self else { return }
+
+        switch result {
+        case .success(let cb):
+          do {
+            let payload = try MessagePayload.decode(cb.decryptedMessage.payload)
+
+            try self.dbManager.getDB().saveMessage(
+              .init(
+                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.replyingTo,
+                roundURL: cb.roundUrl
+              )
+            )
+          } catch {
+            print(error.localizedDescription)
+          }
+        case .failure(let error):
+          print(error.localizedDescription)
+        }
+      })
+    ))
+  }
+
+  func handleGroupRequest(from group: XXClient.Group, messenger: Messenger) {
+    if let _ = try? dbManager.getDB().fetchGroups(.init(id: [group.getId()])).first { return }
+
+    guard var members = try? group.getMembership(), let leader = members.first else {
+      fatalError("Failed to get group membership/leader")
+    }
+
+    try! dbManager.getDB().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! dbManager.getDB().saveMessage(.init(
+        senderId: leader.id,
+        recipientId: nil,
+        groupId: group.getId(),
+        date: Date.fromMSTimestamp(group.getCreatedMS()),
+        status: .received,
+        isUnread: true,
+        text: initMessage
+      ))
+    }
+
+    let friends = try! dbManager.getDB().fetchContacts(.init(
+      id: Set(members.map(\.id)),
+      authStatus: [
+        .friend,
+        .hidden,
+        .requesting,
+        .confirming,
+        .verificationInProgress,
+        .verified,
+        .requested,
+        .requestFailed,
+        .verificationFailed,
+        .confirmationFailed
+      ]
+    ))
+
+    let strangers = Set(members.map(\.id)).subtracting(Set(friends.map(\.id)))
+
+    strangers.forEach {
+      if let stranger = try? dbManager.getDB().fetchContacts(.init(id: [$0])).first {
+        print(">>> This is a stranger, but I already knew about his/her existance: \(stranger.id.base64EncodedString().prefix(10))...")
+      } else {
+        try! dbManager.getDB().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? dbManager.getDB().saveGroupMember(model)
+    }
+
+    do {
+      let multiLookup = try messenger.lookupContacts(ids: strangers.map { $0 })
+
+      for user in multiLookup.contacts {
+        if var foo = try? self.dbManager.getDB().fetchContacts(.init(id: [user.getId()])).first,
+           let username = try? user.getFact(.username)?.value {
+          foo.username = username
+          _ = try? self.dbManager.getDB().saveContact(foo)
+        }
+      }
+    } catch {
+      // TODO
+    }
+  }
+}
+
+
+
+//func handleIncomingTransfer(_ receivedFile: ReceivedFile) {
+//  if var model = try? dbManager.getDB().saveFileTransfer(.init(
+//    id: receivedFile.transferId,
+//    contactId: receivedFile.senderId,
+//    name: receivedFile.name,
+//    type: receivedFile.type,
+//    data: nil,
+//    progress: 0.0,
+//    isIncoming: true,
+//    createdAt: Date()
+//  )) {
+//    try! dbManager.getDB().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? DI.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.dbManager.getDB().saveFileTransfer(model)
+//
+//          case .failure(let error):
+//            print(error.localizedDescription)
+//          }
+//        })
+//      )
+//    } else {
+//      //print(DI.Container.shared.dependencies)
+//    }
+//  }
+//}
diff --git a/Sources/MenuFeature/Controllers/MenuController.swift b/Sources/MenuFeature/Controllers/MenuController.swift
index 1c7623d54d4f74dd0fb30d7c51c4876c067f2db9..e02c7e62f37001cbb9780905c5fe475070d98f62 100644
--- a/Sources/MenuFeature/Controllers/MenuController.swift
+++ b/Sources/MenuFeature/Controllers/MenuController.swift
@@ -1,13 +1,15 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
 
 public final class MenuController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = MenuView()
 
@@ -16,8 +18,14 @@ public final class MenuController: UIViewController {
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
 
-  public init(_ currentItem: MenuItem) {
+  private var navController: UINavigationController?
+
+  public init(
+    _ currentItem: MenuItem,
+    _ navController: UINavigationController? = nil
+  ) {
     self.currentItem = currentItem
+    self.navController = navController
     super.init(nibName: nil, bundle: nil)
   }
 
@@ -57,12 +65,12 @@ public final class MenuController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.lightContent)
+    statusBar.set(.lightContent)
   }
 
   public override func viewWillDisappear(_ animated: Bool) {
     super.viewWillDisappear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
   }
 
   private func setupBindings() {
@@ -74,7 +82,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .scan else { return }
-          self.navigator.perform(PresentScan(on: self.navigationController!))
+          self.navigator.perform(PresentScan(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -86,7 +94,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .profile else { return }
-          self.navigator.perform(PresentProfile(on: self.navigationController!))
+          self.navigator.perform(PresentProfile(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -97,7 +105,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .scan else { return }
-          self.navigator.perform(PresentScan(on: self.navigationController!))
+          self.navigator.perform(PresentScan(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -108,7 +116,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .chats else { return }
-          self.navigator.perform(PresentChatList(on: self.navigationController!))
+          self.navigator.perform(PresentChatList(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -119,7 +127,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .contacts else { return }
-          self.navigator.perform(PresentContactList(on: self.navigationController!))
+          self.navigator.perform(PresentContactList(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -130,7 +138,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .settings else { return }
-          self.navigator.perform(PresentSettings(on: self.navigationController!))
+          self.navigator.perform(PresentSettings(on: self.navController!))
         }
       }.store(in: &cancellables)
 
@@ -158,7 +166,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .requests else { return }
-          self.navigator.perform(PresentRequests(on: self.navigationController!))
+          self.navigator.perform(PresentRequests(on: self.navController!))
         }
       }.store(in: &cancellables)
 
diff --git a/Sources/MenuFeature/ViewModels/MenuViewModel.swift b/Sources/MenuFeature/ViewModels/MenuViewModel.swift
index 322aae91c2aea30dd86ce5c29fb277ba169f7155..3005d8e2a7b22b375f44dfdac8635fd31f8c47d3 100644
--- a/Sources/MenuFeature/ViewModels/MenuViewModel.swift
+++ b/Sources/MenuFeature/ViewModels/MenuViewModel.swift
@@ -1,60 +1,61 @@
 import Combine
+import AppCore
 import XXModels
 import XXClient
 import Defaults
 import Foundation
 import ReportingFeature
-import DI
+import ComposableArchitecture
 
 final class MenuViewModel {
-    @Dependency var database: Database
-    @Dependency var reportingStatus: ReportingStatus
-
-    @KeyObject(.avatar, defaultValue: nil) var avatar: Data?
-    @KeyObject(.username, defaultValue: "") var username: String
-
-    var requestCount: AnyPublisher<Int, Never> {
-        let groupQuery = Group.Query(
-            authStatus: [.pending],
-            isLeaderBlocked: reportingStatus.isEnabled() ? false : nil,
-            isLeaderBanned: reportingStatus.isEnabled() ? false : nil
-        )
-
-        let contactsQuery = Contact.Query(
-            authStatus: [
-                .verified,
-                .confirming,
-                .confirmationFailed,
-                .verificationFailed,
-                .verificationInProgress
-            ],
-            isBlocked: reportingStatus.isEnabled() ? false : nil,
-            isBanned: reportingStatus.isEnabled() ? false : nil
-        )
-
-        return Publishers.CombineLatest(
-          database.fetchContactsPublisher(contactsQuery)
-            .replaceError(with: []),
-          database.fetchGroupsPublisher(groupQuery)
-            .replaceError(with: [])
-        )
-        .map { $0.0.count + $0.1.count }
-        .eraseToAnyPublisher()
-    }
-
-    var xxdk: String {
-        GetVersion.live()
-    }
-
-    var build: String {
-        Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
-    }
-
-    var version: String {
-        Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
-    }
-
-    var referralDeeplink: String {
-        "https://elixxir.io/connect?username=\(username)"
-    }
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  @KeyObject(.avatar, defaultValue: nil) var avatar: Data?
+  @KeyObject(.username, defaultValue: "") var username: String
+
+  var requestCount: AnyPublisher<Int, Never> {
+    let groupQuery = Group.Query(
+      authStatus: [.pending],
+      isLeaderBlocked: reportingStatus.isEnabled() ? false : nil,
+      isLeaderBanned: reportingStatus.isEnabled() ? false : nil
+    )
+
+    let contactsQuery = Contact.Query(
+      authStatus: [
+        .verified,
+        .confirming,
+        .confirmationFailed,
+        .verificationFailed,
+        .verificationInProgress
+      ],
+      isBlocked: reportingStatus.isEnabled() ? false : nil,
+      isBanned: reportingStatus.isEnabled() ? false : nil
+    )
+
+    return Publishers.CombineLatest(
+      try! dbManager.getDB().fetchContactsPublisher(contactsQuery)
+        .replaceError(with: []),
+      try! dbManager.getDB().fetchGroupsPublisher(groupQuery)
+        .replaceError(with: [])
+    )
+    .map { $0.0.count + $0.1.count }
+    .eraseToAnyPublisher()
+  }
+
+  var xxdk: String {
+    GetVersion.live()
+  }
+
+  var build: String {
+    Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
+  }
+
+  var version: String {
+    Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
+  }
+
+  var referralDeeplink: String {
+    "https://elixxir.io/connect?username=\(username)"
+  }
 }
diff --git a/Sources/MenuFeature/Views/MenuHeaderView.swift b/Sources/MenuFeature/Views/MenuHeaderView.swift
index 2f925646b3b03c3aec498ccb67578a1b4f40fb89..eaea1321b5ea8f1eaaf7a7ebbda4c0190433979d 100644
--- a/Sources/MenuFeature/Views/MenuHeaderView.swift
+++ b/Sources/MenuFeature/Views/MenuHeaderView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class MenuHeaderView: UIView {
     let nameButton = UIButton()
diff --git a/Sources/MenuFeature/Views/MenuSectionButton.swift b/Sources/MenuFeature/Views/MenuSectionButton.swift
index c5f6ea371a10f0ff3fc087b31f6dc744e11fd4a9..2432cdf6b8cb86833e407c9f5e22deeed2def9f5 100644
--- a/Sources/MenuFeature/Views/MenuSectionButton.swift
+++ b/Sources/MenuFeature/Views/MenuSectionButton.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class MenuSectionButton: UIControl {
     let titleLabel = UILabel()
diff --git a/Sources/MenuFeature/Views/MenuView.swift b/Sources/MenuFeature/Views/MenuView.swift
index 8e83eacb17ce598f2a72ad0d97a1db064c6f1904..e62deae1b0ef07fdb6938845aec4048a824d2386 100644
--- a/Sources/MenuFeature/Views/MenuView.swift
+++ b/Sources/MenuFeature/Views/MenuView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class MenuView: UIView {
   let buildLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
index 05f0be5bbc98ea56a1e57ada2328382b754cb712..6fa2993c058cd37554b92efd4dea45209a490cfc 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
@@ -1,16 +1,16 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
 import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
-import StatusBarFeature
 import ScrollViewController
-import ComposableArchitecture
 
 public final class OnboardingCodeController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = OnboardingCodeView()
   private lazy var scrollViewController = ScrollViewController()
@@ -41,7 +41,7 @@ public final class OnboardingCodeController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
index df1fc7bfebd56330f8e76f518d9ffde6769f74e7..d15c6594393c5cb7942d78abd3173378dc4756b4 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
@@ -1,16 +1,16 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
 import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
-import StatusBarFeature
 import ScrollViewController
-import ComposableArchitecture
 
 public final class OnboardingEmailController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = OnboardingEmailView()
   private lazy var scrollViewController = ScrollViewController()
@@ -22,7 +22,7 @@ public final class OnboardingEmailController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = " "
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
index 0f4eebf87044c777e9af241523077fd1634f1d82..466a45994a90979bdcbf09e427efad88cef93b24 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
@@ -1,16 +1,16 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
 import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
-import StatusBarFeature
 import ScrollViewController
-import ComposableArchitecture
 
 public final class OnboardingPhoneController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = OnboardingPhoneView()
   private lazy var scrollViewController = ScrollViewController()
@@ -22,7 +22,7 @@ public final class OnboardingPhoneController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index 4e09d6b6609e27454822912e2b844bf8b3e4aa1b..0fd4158db96cda5d8f7cea46388de3b6890a7864 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -1,6 +1,6 @@
 import UIKit
 import Combine
-import Navigation
+import AppNavigation
 import ComposableArchitecture
 
 public final class OnboardingStartController: UIViewController {
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index 42f4f18981fabb12a44713d22f2904a4e831af54..619a983b7149929bf7ca1232aff937bcaf34baa8 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -1,16 +1,16 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
 import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
-import StatusBarFeature
 import ScrollViewController
-import ComposableArchitecture
 
 public final class OnboardingUsernameController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = OnboardingUsernameView()
   private lazy var scrollViewController = ScrollViewController()
@@ -22,7 +22,7 @@ public final class OnboardingUsernameController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
index 09a9221ba5765e85d92a9626b41377566a0977c2..f3bc2af0248b805fae258212d7573d89c9586dc5 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
@@ -2,15 +2,15 @@ import UIKit
 import Shared
 import Combine
 import Defaults
-import Navigation
+import AppCore
+import Dependencies
 import AppResources
+import AppNavigation
 import DrawerFeature
-import StatusBarFeature
-import ComposableArchitecture
 
 public final class OnboardingWelcomeController: UIViewController {
   @Dependency(\.navigator) var navigator: Navigator
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   @KeyObject(.username, defaultValue: "") var username: String
 
@@ -25,7 +25,7 @@ public final class OnboardingWelcomeController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/OnboardingFeature/OnboardingDependencies.swift b/Sources/OnboardingFeature/OnboardingDependencies.swift
deleted file mode 100644
index fe3dce7f61997d7fc4b4d80d2d4b20caf358bcf4..0000000000000000000000000000000000000000
--- a/Sources/OnboardingFeature/OnboardingDependencies.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-import Navigation
-import Dependencies
-
-private enum NavigatorKey: DependencyKey {
-  static let liveValue: Navigator = CombinedNavigator.core
-  static let testValue: Navigator = UnimplementedNavigator()
-}
-
-extension DependencyValues {
-  var navigator: Navigator {
-    get { self[NavigatorKey.self] }
-    set { self[NavigatorKey.self] = newValue }
-  }
-}
-
-import UIKit
-import XCTestDynamicOverlay
-import ComposableArchitecture
-
-public struct PresentStep: Navigation.Action, Equatable {
-  public init(viewController: UIViewController, from: UIViewController) {
-    self.viewController = viewController
-    self.from = from
-  }
-
-  public var viewController: UIViewController
-  public var from: UIViewController
-}
-
-struct PresentStepNavigator: Navigation.TypedNavigator {
-  @Dependency(\.navigator) var navigator
-
-  func perform(_ action: PresentStep, completion: @escaping () -> Void) {
-    guard let navigationController = action.from.navigationController else {
-      completion()
-      return
-    }
-    navigator.perform(
-      SetStack(
-        navigationController.viewControllers + [action.viewController],
-        on: navigationController
-      ),
-      completion: completion
-    )
-  }
-}
-
-public struct DismissToStep: Navigation.Action, Equatable {
-  public init(viewController: UIViewController) {
-    self.viewController = viewController
-  }
-
-  public var viewController: UIViewController
-}
-
-struct DismissToStepNavigator: Navigation.TypedNavigator {
-  @Dependency(\.navigator) var navigator
-
-  func perform(_ action: DismissToStep, completion: @escaping () -> Void) {
-    guard let navigationController = action.viewController.navigationController else {
-      completion()
-      return
-    }
-    navigator.perform(
-      PopTo(action.viewController, on: navigationController),
-      completion: completion
-    )
-  }
-}
-
-extension CombinedNavigator {
-  public static let core = CombinedNavigator(
-    SetStackNavigator(),
-    PopToNavigator(),
-    PresentStepNavigator(),
-    DismissToStepNavigator()
-  )
-}
-
-public struct UnimplementedNavigator: Navigator {
-  public init() {}
-
-  public func perform(_ action: Navigation.Action, completion: @escaping () -> Void) {
-    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.perform not implemented")
-  }
-
-  public func canPerform(_ action: Action) -> Bool {
-    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.canPerform not implemented")
-    return false
-  }
-}
diff --git a/Sources/PermissionsFeature/Dependency.swift b/Sources/PermissionsFeature/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..766f239ff492ca00b4ed0fc9a8afaa879818812b
--- /dev/null
+++ b/Sources/PermissionsFeature/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum PermissionsDependencyKey: DependencyKey {
+  static let liveValue: PermissionsManager = .live
+  static let testValue: PermissionsManager = .unimplemented
+}
+
+extension DependencyValues {
+  public var permissions: PermissionsManager {
+    get { self[PermissionsDependencyKey.self] }
+    set { self[PermissionsDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/PermissionsFeature/PermissionPush.swift b/Sources/PermissionsFeature/PermissionPush.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a4be4209b7656f59615ca95b6a89ce187ccf5515
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionPush.swift
@@ -0,0 +1,66 @@
+import UserNotifications
+import XCTestDynamicOverlay
+
+public struct PermissionPush {
+  public var status: PermissionPushStatus
+  public var request: PermissionPushRequest
+
+  public static let live = PermissionPush(
+    status: .live,
+    request: .live
+  )
+  public static let unimplemented = PermissionPush(
+    status: .unimplemented,
+    request: .unimplemented
+  )
+}
+
+public struct PermissionPushRequest {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+}
+
+extension PermissionPushRequest {
+  public static let live = PermissionPushRequest { completion in
+    let current = UNUserNotificationCenter.current()
+    current.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
+      if error != nil {
+        completion(false)
+        return
+      }
+      completion(granted)
+    }
+  }
+}
+
+extension PermissionPushRequest {
+  public static let unimplemented = PermissionPushRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct PermissionPushStatus {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+}
+
+extension PermissionPushStatus {
+  public static let live = PermissionPushStatus { completion in
+    let current = UNUserNotificationCenter.current()
+    current.getNotificationSettings {
+      completion($0.authorizationStatus == .authorized)
+    }
+  }
+}
+
+extension PermissionPushStatus {
+  public static let unimplemented = PermissionPushStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/PermissionsFeature/PermissionType.swift b/Sources/PermissionsFeature/PermissionType.swift
deleted file mode 100644
index 93b8ba3906708b240dc45fb39bbca98173ae0495..0000000000000000000000000000000000000000
--- a/Sources/PermissionsFeature/PermissionType.swift
+++ /dev/null
@@ -1,5 +0,0 @@
-public enum PermissionType: Int {
-  case camera
-  case library
-  case microphone
-}
diff --git a/Sources/PermissionsFeature/PermissionsManager.swift b/Sources/PermissionsFeature/PermissionsManager.swift
index 89fd4b377e122725bd112bc4a1fdc3c760688a61..33373e6e3fbf9faf738cbd80f89a24c2ee13f7eb 100644
--- a/Sources/PermissionsFeature/PermissionsManager.swift
+++ b/Sources/PermissionsFeature/PermissionsManager.swift
@@ -1,33 +1,22 @@
 public struct PermissionsManager {
+  public var push: PermissionPush
   public var camera: PermissionCamera
   public var library: PermissionLibrary
   public var microphone: PermissionMicrophone
   public var biometrics: PermissionBiometrics
 
   public static let live = PermissionsManager(
+    push: .live,
     camera: .live,
     library: .live,
     microphone: .live,
     biometrics: .live
   )
   public static let unimplemented = PermissionsManager(
+    push: .unimplemented,
     camera: .unimplemented,
     library: .unimplemented,
     microphone: .unimplemented,
     biometrics: .unimplemented
   )
 }
-
-import Dependencies
-
-private enum PermissionsDependencyKey: DependencyKey {
-  static let liveValue: PermissionsManager = .live
-  static let testValue: PermissionsManager = .unimplemented
-}
-
-extension DependencyValues {
-  public var permissions: PermissionsManager {
-    get { self[PermissionsDependencyKey.self] }
-    set { self[PermissionsDependencyKey.self] = newValue }
-  }
-}
diff --git a/Sources/ProcessBannedList/Dependency.swift b/Sources/ProcessBannedList/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1f02756a5541c2907e9cb6f23fe45510c43afa16
--- /dev/null
+++ b/Sources/ProcessBannedList/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum ProcessBannedListDependencyKey: DependencyKey {
+  static let liveValue: ProcessBannedList = .live
+  static let testValue: ProcessBannedList = .unimplemented
+}
+
+extension DependencyValues {
+  public var processBannedList: ProcessBannedList {
+    get { self[ProcessBannedListDependencyKey.self] }
+    set { self[ProcessBannedListDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/ProcessBannedList/ProcessBannedList.swift b/Sources/ProcessBannedList/ProcessBannedList.swift
new file mode 100644
index 0000000000000000000000000000000000000000..900738b323abf85587789fa040e891563cd9f85a
--- /dev/null
+++ b/Sources/ProcessBannedList/ProcessBannedList.swift
@@ -0,0 +1,64 @@
+import Foundation
+import SwiftCSV
+import XCTestDynamicOverlay
+
+public struct ProcessBannedList {
+  public enum ElementError: Swift.Error {
+    case missingUserId
+    case invalidUserId(String)
+  }
+
+  public enum Error: Swift.Error {
+    case invalidData
+    case csv(Swift.Error)
+  }
+
+  public typealias ForEach = (Result<Data, ElementError>) -> Void
+  public typealias Completion = (Result<Void, Error>) -> Void
+
+  public var run: (Data, ForEach, Completion) -> Void
+
+  public func callAsFunction(
+    data: Data,
+    forEach: ForEach,
+    completion: Completion
+  ) {
+    run(data, forEach, completion)
+  }
+}
+
+extension ProcessBannedList {
+  public static let live = ProcessBannedList { data, forEach, completion in
+    guard let csvString = String(data: data, encoding: .utf8) else {
+      completion(.failure(.invalidData))
+      return
+    }
+    let csv: EnumeratedCSV
+    do {
+      csv = try EnumeratedCSV(string: csvString)
+    }
+    catch {
+      completion(.failure(.csv(error)))
+      return
+    }
+    csv.rows.forEach { row in
+      guard let userIdString = row.first else {
+        forEach(.failure(.missingUserId))
+        return
+      }
+      guard let userId = Data(base64Encoded: userIdString) else {
+        forEach(.failure(.invalidUserId(userIdString)))
+        return
+      }
+      forEach(.success(userId))
+    }
+    completion(.success(()))
+  }
+}
+
+extension ProcessBannedList {
+  public static let unimplemented = ProcessBannedList { _, _, _ in
+    let run: () -> Void = XCTUnimplemented("\(Self.self)")
+    run()
+  }
+}
diff --git a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
index 8f6ff16f9df23b36fee5b4ff316a4044f40abe32..d5d640db0263cf29abda90a9b1ec962e89e9081c 100644
--- a/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileCodeController.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
-import DI
+import AppCore
+import AppResources
+import Dependencies
+import AppNavigation
 import ScrollViewController
 
 public final class ProfileCodeController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ProfileCodeView()
   private lazy var scrollViewController = ScrollViewController()
diff --git a/Sources/ProfileFeature/Controllers/ProfileController.swift b/Sources/ProfileFeature/Controllers/ProfileController.swift
index 3662169233784d0c2f6420e0e5d1c512a414334c..23dca61bf795b7ede333f78d8ed0c2d7fdfa2588 100644
--- a/Sources/ProfileFeature/Controllers/ProfileController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileController.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
+import ComposableArchitecture
 
 public final class ProfileController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ProfileView()
 
@@ -21,7 +23,7 @@ public final class ProfileController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.lightContent)
+    statusBar.set(.lightContent)
     navigationController?.navigationBar
       .customize(backgroundColor: Asset.neutralBody.color)
     viewModel.refresh()
diff --git a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
index 1bfc1c789b7f4de906f56aaad09c94f08a8fb7ba..ef9ef2f8f501ae6160d96cd72376d33222d9cdac 100644
--- a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
@@ -1,13 +1,15 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import AppResources
+import AppNavigation
 import ScrollViewController
+import ComposableArchitecture
 
 public final class ProfileEmailController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ProfileEmailView()
   private lazy var scrollViewController = ScrollViewController()
@@ -18,7 +20,7 @@ public final class ProfileEmailController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(backgroundColor: Asset.neutralWhite.color)
   }
 
diff --git a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
index bd9689a44bcc96f648bb1c6427de7b15148957a7..99ac70b864328dd362fe88a2487fc3ba8fec2ce2 100644
--- a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
@@ -1,13 +1,15 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import AppResources
+import Dependencies
+import AppNavigation
 import ScrollViewController
 
 public final class ProfilePhoneController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ProfilePhoneView()
   private lazy var scrollViewController = ScrollViewController()
@@ -18,7 +20,7 @@ public final class ProfilePhoneController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar
       .customize(backgroundColor: Asset.neutralWhite.color)
   }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
index 9a1638ec536cdc728a5eb1b55c81dd93faecb24a..a018da77f237fc1c4b604ea791aa0289452638d0 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileCodeViewModel.swift
@@ -1,12 +1,12 @@
 import Shared
 import Combine
+import AppCore
 import Defaults
 import XXClient
 import InputField
 import Foundation
-import CombineSchedulers
 import XXMessengerClient
-import DI
+import ComposableArchitecture
 
 final class ProfileCodeViewModel {
   struct ViewState: Equatable {
@@ -20,8 +20,10 @@ final class ProfileCodeViewModel {
     stateSubject.eraseToAnyPublisher()
   }
 
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
 
@@ -30,7 +32,6 @@ final class ProfileCodeViewModel {
   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,
@@ -61,8 +62,8 @@ final class ProfileCodeViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       do {
         try self.messenger.ud.get()!.confirmFact(
@@ -75,11 +76,11 @@ final class ProfileCodeViewModel {
           self.phone = self.content
         }
         self.timer?.invalidate()
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.didConfirm = true
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.hudManager.show(.init(content: xxError))
       }
     }
   }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
index fd27e4f0081cd1bda51e10fa569153943c1916c9..96210b7dc00867639c7861d377d868df11bb8b62 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileEmailViewModel.swift
@@ -1,11 +1,12 @@
 import Shared
 import Combine
+import AppCore
 import XXClient
 import Foundation
 import InputField
 import CombineSchedulers
 import XXMessengerClient
-import DI
+import ComposableArchitecture
 
 final class ProfileEmailViewModel {
   struct ViewState: Equatable {
@@ -13,16 +14,16 @@ final class ProfileEmailViewModel {
     var confirmationId: String?
     var status: InputField.ValidationStatus = .unknown(nil)
   }
-  
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
 
   var statePublisher: AnyPublisher<ViewState, Never> {
     stateSubject.eraseToAnyPublisher()
   }
 
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
-  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func clearUp() {
     stateSubject.value.confirmationId = nil
@@ -34,17 +35,17 @@ final class ProfileEmailViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       do {
         let confirmationId = try self.messenger.ud.get()!.sendRegisterFact(
           .init(type: .email, value: self.stateSubject.value.input)
         )
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.confirmationId = confirmationId
       } catch {
-        self.hudController.dismiss()
+        self.hudManager.hide()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.stateSubject.value.status = .invalid(xxError)
       }
diff --git a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
index 2eadd36da44361a596cc1ddaa81dbbefb60c5d0b..90387a69dde095491775b47cd4e138ae6786f483 100644
--- a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
@@ -1,12 +1,13 @@
 import Shared
 import Combine
+import AppCore
 import XXClient
 import InputField
 import Foundation
+import Dependencies
 import CombineSchedulers
 import XXMessengerClient
 import CountryListFeature
-import DI
 
 final class ProfilePhoneViewModel {
   struct ViewState: Equatable {
@@ -17,15 +18,15 @@ final class ProfilePhoneViewModel {
     var country: Country = .fromMyPhone()
   }
 
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
 
   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) {
     stateSubject.value.input = string
@@ -42,8 +43,8 @@ final class ProfilePhoneViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       let content = "\(self.stateSubject.value.input)\(self.stateSubject.value.country.code)"
       do {
@@ -51,12 +52,12 @@ final class ProfilePhoneViewModel {
           .init(type: .phone, value: content)
         )
 
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.content = content
         self.stateSubject.value.confirmationId = confirmationId
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.hudManager.show(.init(content: xxError))
       }
     }
   }
diff --git a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
index 17daebf9d9bbbba24b545c59f7dca5c8a0e88660..07ab592ebd904e0a1dc91314e7b616a5cea7a646 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
@@ -1,15 +1,15 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import Defaults
 import XXClient
-import Foundation
-import Permissions
 import BackupFeature
 import XXMessengerClient
 import CombineSchedulers
 import CountryListFeature
-import DI
+import PermissionsFeature
+import ComposableArchitecture
 
 enum ProfileNavigationRoutes {
   case none
@@ -31,21 +31,24 @@ final class ProfileViewModel {
   @KeyObject(.sharingEmail, defaultValue: false) var isEmailSharing: Bool
   @KeyObject(.sharingPhone, defaultValue: false) var isPhoneSharing: Bool
 
-  @Dependency var messenger: Messenger
-  @Dependency var backupService: BackupService
-  @Dependency var hudController: HUDController
-  @Dependency var permissions: PermissionHandling
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.backupService) var backupService: BackupService
+  @Dependency(\.permissions) var permissions: PermissionsManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
 
   var name: String { username! }
 
-  var state: AnyPublisher<ProfileViewState, Never> { stateRelay.eraseToAnyPublisher() }
+  var state: AnyPublisher<ProfileViewState, Never> {
+    stateRelay.eraseToAnyPublisher()
+  }
   private let stateRelay = CurrentValueSubject<ProfileViewState, Never>(.init())
 
-  var navigation: AnyPublisher<ProfileNavigationRoutes, Never> { navigationRoutes.eraseToAnyPublisher() }
+  var navigation: AnyPublisher<ProfileNavigationRoutes, Never> {
+    navigationRoutes.eraseToAnyPublisher()
+  }
   private let navigationRoutes = PassthroughSubject<ProfileNavigationRoutes, Never>()
 
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-
   init() {
     refresh()
   }
@@ -66,7 +69,7 @@ final class ProfileViewModel {
   }
 
   func didRequestLibraryAccess() {
-    if permissions.isPhotosAllowed {
+    if permissions.library.status() {
       navigationRoutes.send(.library)
     } else {
       navigationRoutes.send(.libraryPermission)
@@ -83,11 +86,10 @@ final class ProfileViewModel {
   }
 
   func didTapDelete(isEmail: Bool) {
-    hudController.show()
+    hudManager.show()
 
-    backgroundScheduler.schedule { [weak self] in
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
-
       do {
         try self.messenger.ud.get()!.removeFact(
           .init(
@@ -95,7 +97,6 @@ final class ProfileViewModel {
             value: isEmail ? self.emailStored! : self.phoneStored!
           )
         )
-
         if isEmail {
           self.emailStored = nil
           self.isEmailSharing = false
@@ -103,13 +104,12 @@ final class ProfileViewModel {
           self.phoneStored = nil
           self.isPhoneSharing = false
         }
-
         self.backupService.didUpdateFacts()
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.refresh()
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.hudManager.show(.init(content: xxError))
       }
     }
   }
diff --git a/Sources/ProfileFeature/Views/ProfileCodeView.swift b/Sources/ProfileFeature/Views/ProfileCodeView.swift
index f8d7199bb22c5b25af077cacd7315774b83ff5fe..dc4fb0310ff4bcbdf5736878b5c4e984a7472686 100644
--- a/Sources/ProfileFeature/Views/ProfileCodeView.swift
+++ b/Sources/ProfileFeature/Views/ProfileCodeView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class ProfileCodeView: UIView {
     let titleLabel = UILabel()
diff --git a/Sources/ProfileFeature/Views/ProfileEmailView.swift b/Sources/ProfileFeature/Views/ProfileEmailView.swift
index 185c0ef797ec8574a31e722dc3478bac3d12fe5c..6c689f68169a7b55261c7444f6c7e3a4e5fe2026 100644
--- a/Sources/ProfileFeature/Views/ProfileEmailView.swift
+++ b/Sources/ProfileFeature/Views/ProfileEmailView.swift
@@ -1,74 +1,75 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class ProfileEmailView: UIView {
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-    let inputField = InputField()
-    let saveButton = CapsuleButton()
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  let inputField = InputField()
+  let saveButton = CapsuleButton()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        titleLabel.text = Localized.Profile.EmailScreen.title
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
-        imageView.contentMode = .center
-        imageView.image = Asset.profileEmail.image
-        saveButton.setStyle(.brandColored)
-        saveButton.setTitle(Localized.Profile.EmailScreen.action, for: .normal)
+    titleLabel.text = Localized.Profile.EmailScreen.title
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
+    imageView.contentMode = .center
+    imageView.image = Asset.profileEmail.image
+    saveButton.setStyle(.brandColored)
+    saveButton.setTitle(Localized.Profile.EmailScreen.action, for: .normal)
 
-        inputField.setup(
-            title: Localized.Profile.EmailScreen.input,
-            placeholder: Localized.Profile.EmailScreen.input,
-            subtitleColor: Asset.neutralWeak.color,
-            allowsEmptySpace: false,
-            keyboardType: .emailAddress,
-            autocapitalization: .none,
-            contentType: .emailAddress
-        )
+    inputField.setup(
+      title: Localized.Profile.EmailScreen.input,
+      placeholder: Localized.Profile.EmailScreen.input,
+      subtitleColor: Asset.neutralWeak.color,
+      allowsEmptySpace: false,
+      keyboardType: .emailAddress,
+      autocapitalization: .none,
+      contentType: .emailAddress
+    )
 
-        addSubview(imageView)
-        addSubview(titleLabel)
-        addSubview(inputField)
-        addSubview(saveButton)
+    addSubview(imageView)
+    addSubview(titleLabel)
+    addSubview(inputField)
+    addSubview(saveButton)
 
-        imageView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(60)
-            make.centerX.equalToSuperview()
-        }
+    imageView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(60)
+      make.centerX.equalToSuperview()
+    }
 
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(imageView.snp.bottom).offset(39)
-            make.centerX.equalToSuperview()
-        }
+    titleLabel.snp.makeConstraints { make in
+      make.top.equalTo(imageView.snp.bottom).offset(39)
+      make.centerX.equalToSuperview()
+    }
 
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(35)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
+    inputField.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(35)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+    }
 
-        saveButton.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(40)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
-        }
+    saveButton.snp.makeConstraints { make in
+      make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(40)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+      make.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
 
-        switch status {
-        case .valid:
-            saveButton.isEnabled = true
-        case .invalid, .unknown:
-            saveButton.isEnabled = false
-        }
+    switch status {
+    case .valid:
+      saveButton.isEnabled = true
+    case .invalid, .unknown:
+      saveButton.isEnabled = false
     }
+  }
 }
diff --git a/Sources/ProfileFeature/Views/ProfilePhoneView.swift b/Sources/ProfileFeature/Views/ProfilePhoneView.swift
index 12f5062fd269d5092a036685943d260304b5b4a0..1dccecfa1276e2983520b01e792ff83d762d527c 100644
--- a/Sources/ProfileFeature/Views/ProfilePhoneView.swift
+++ b/Sources/ProfileFeature/Views/ProfilePhoneView.swift
@@ -1,73 +1,74 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class ProfilePhoneView: UIView {
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-    let inputField = InputField()
-    let saveButton = CapsuleButton()
-    
-    init() {
-        super.init(frame: .zero)
-        
-        titleLabel.text = "Add Phone"
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
-        imageView.contentMode = .center
-        imageView.image = Asset.profilePhone.image
-        saveButton.setStyle(.brandColored)
-        saveButton.setTitle(Localized.Profile.PhoneScreen.action, for: .normal)
-        
-        inputField.setup(
-            style: .phone,
-            title: Localized.Profile.PhoneScreen.input,
-            placeholder: "10651613216",
-            subtitleColor: Asset.neutralWeak.color,
-            keyboardType: .phonePad,
-            contentType: .telephoneNumber
-        )
-        
-        addSubview(imageView)
-        addSubview(titleLabel)
-        addSubview(inputField)
-        addSubview(saveButton)
-        
-        imageView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(60)
-            make.centerX.equalToSuperview()
-        }
-        
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(imageView.snp.bottom).offset(39)
-            make.centerX.equalToSuperview()
-        }
-        
-        inputField.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(35)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
-        
-        saveButton.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(40)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
-        }
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  let inputField = InputField()
+  let saveButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+
+    titleLabel.text = "Add Phone"
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 32.0)
+    imageView.contentMode = .center
+    imageView.image = Asset.profilePhone.image
+    saveButton.setStyle(.brandColored)
+    saveButton.setTitle(Localized.Profile.PhoneScreen.action, for: .normal)
+
+    inputField.setup(
+      style: .phone,
+      title: Localized.Profile.PhoneScreen.input,
+      placeholder: "10651613216",
+      subtitleColor: Asset.neutralWeak.color,
+      keyboardType: .phonePad,
+      contentType: .telephoneNumber
+    )
+
+    addSubview(imageView)
+    addSubview(titleLabel)
+    addSubview(inputField)
+    addSubview(saveButton)
+
+    imageView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(60)
+      make.centerX.equalToSuperview()
+    }
+
+    titleLabel.snp.makeConstraints { make in
+      make.top.equalTo(imageView.snp.bottom).offset(39)
+      make.centerX.equalToSuperview()
     }
-    
-    required init?(coder: NSCoder) { nil }
-    
-    func update(status: InputField.ValidationStatus) {
-        inputField.update(status: status)
-        
-        switch status {
-        case .valid:
-            saveButton.isEnabled = true
-        case .invalid, .unknown:
-            saveButton.isEnabled = false
-        }
+
+    inputField.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(35)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+    }
+
+    saveButton.snp.makeConstraints { make in
+      make.top.greaterThanOrEqualTo(inputField.snp.bottom).offset(40)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+      make.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func update(status: InputField.ValidationStatus) {
+    inputField.update(status: status)
+
+    switch status {
+    case .valid:
+      saveButton.isEnabled = true
+    case .invalid, .unknown:
+      saveButton.isEnabled = false
     }
+  }
 }
diff --git a/Sources/ProfileFeature/Views/ProfileView.swift b/Sources/ProfileFeature/Views/ProfileView.swift
index e95e3e63c08f97b705a4da31c9e3264d8c1ba1f4..55081d330c759c7bcc6fc798c9bc92a33969990d 100644
--- a/Sources/ProfileFeature/Views/ProfileView.swift
+++ b/Sources/ProfileFeature/Views/ProfileView.swift
@@ -1,43 +1,44 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ProfileView: UIView {
-    let stackView = UIStackView()
-    let cardComponent = AvatarCardComponent()
-    let emailView = AttributeComponent()
-    let phoneView = AttributeComponent()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        let emailTitle = Localized.Profile.Email.title
-        let phoneTitle = Localized.Profile.Phone.title
-
-        emailView.set(title: emailTitle, style: .interactive)
-        phoneView.set(title: phoneTitle, style: .interactive)
-
-        stackView.spacing = 41
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(emailView)
-        stackView.addArrangedSubview(phoneView)
-
-        addSubview(stackView)
-        addSubview(cardComponent)
-
-        cardComponent.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalTo(cardComponent.snp.bottom).offset(24)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-26)
-            make.bottom.lessThanOrEqualToSuperview()
-        }
+  let stackView = UIStackView()
+  let cardComponent = AvatarCardComponent()
+  let emailView = AttributeComponent()
+  let phoneView = AttributeComponent()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    let emailTitle = Localized.Profile.Email.title
+    let phoneTitle = Localized.Profile.Phone.title
+
+    emailView.set(title: emailTitle, style: .interactive)
+    phoneView.set(title: phoneTitle, style: .interactive)
+
+    stackView.spacing = 41
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(emailView)
+    stackView.addArrangedSubview(phoneView)
+
+    addSubview(stackView)
+    addSubview(cardComponent)
+
+    cardComponent.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+    }
+
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(cardComponent.snp.bottom).offset(24)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-26)
+      $0.bottom.lessThanOrEqualToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/PushFeature/MockPushHandler.swift b/Sources/PushFeature/MockPushHandler.swift
index 41aced17ade52d9c4b02ec092feec29276fc21fb..385175c34179ad084651fd87a6d873612d758cff 100644
--- a/Sources/PushFeature/MockPushHandler.swift
+++ b/Sources/PushFeature/MockPushHandler.swift
@@ -1,39 +1,39 @@
 import UIKit
 
 public struct MockPushHandler: PushHandling {
-    public init() {}
-
-    public func registerToken(_ token: Data) {
-        // TODO
-    }
-
-    public func requestAuthorization(
-        _ completion: @escaping (Result<Bool, Error>) -> Void
-    ) {
-        completion(.success(true))
-    }
-
-    public func handlePush(
-        _ notification: [AnyHashable : Any],
-        _ completion: @escaping (UIBackgroundFetchResult) -> Void
-    ) {
-        completion(.noData)
-    }
-
-    public func handlePush(
-        _ request: UNNotificationRequest,
-        _ completion: @escaping (UNNotificationContent) -> Void
-    ) {
-        let content = UNMutableNotificationContent()
-        content.title = String(describing: Self.self)
-        completion(content)
-    }
-
-    public func handleAction(
-        _ router: PushRouter,
-        _ userInfo: [AnyHashable : Any],
-        _ completion: @escaping () -> Void
-    ) {
-        completion()
-    }
+  public init() {}
+  
+  public func registerToken(_ token: Data) {
+    // TODO
+  }
+  
+  public func requestAuthorization(
+    _ completion: @escaping (Result<Bool, Error>) -> Void
+  ) {
+    completion(.success(true))
+  }
+  
+  public func handlePush(
+    _ notification: [AnyHashable : Any],
+    _ completion: @escaping (UIBackgroundFetchResult) -> Void
+  ) {
+    completion(.noData)
+  }
+  
+  public func handlePush(
+    _ request: UNNotificationRequest,
+    _ completion: @escaping (UNNotificationContent) -> Void
+  ) {
+    let content = UNMutableNotificationContent()
+    content.title = String(describing: Self.self)
+    completion(content)
+  }
+  
+  public func handleAction(
+    _ router: PushRouter,
+    _ userInfo: [AnyHashable : Any],
+    _ completion: @escaping () -> Void
+  ) {
+    completion()
+  }
 }
diff --git a/Sources/PushFeature/PushExtractor.swift b/Sources/PushFeature/PushExtractor.swift
index 75c6a69070d0d301498122896ac90ab2ab48c987..ee584586e407307ac3bf7bc8e71f597e19df5485 100644
--- a/Sources/PushFeature/PushExtractor.swift
+++ b/Sources/PushFeature/PushExtractor.swift
@@ -2,7 +2,6 @@ import XXModels
 import XXClient
 import Foundation
 import XXMessengerClient
-import DI
 
 public struct PushExtractor {
   enum Constants {
diff --git a/Sources/PushFeature/PushHandler.swift b/Sources/PushFeature/PushHandler.swift
index 1be9e28d179954a659b615f236825a753bd468bf..86bb7a29a27d702e639f1c8813340b43f37e7907 100644
--- a/Sources/PushFeature/PushHandler.swift
+++ b/Sources/PushFeature/PushHandler.swift
@@ -1,11 +1,12 @@
 import UIKit
+import AppCore
 import Defaults
 import XXClient
 import XXModels
 import XXDatabase
-import XXMessengerClient
 import ReportingFeature
-import DI
+import XXMessengerClient
+import ComposableArchitecture
 
 public final class PushHandler: PushHandling {
   private enum Constants {
@@ -13,7 +14,7 @@ public final class PushHandler: PushHandling {
     static let usernamesSetting = "isShowingUsernames"
   }
 
-  @Dependency var messenger: Messenger
+  @Dependency(\.app.messenger) var messenger: Messenger
 
   @KeyObject(.pushNotifications, defaultValue: false) var isPushEnabled: Bool
 
diff --git a/Sources/PushFeature/PushHandling.swift b/Sources/PushFeature/PushHandling.swift
index c17c7e600d9c8f3ed222f3e7b8e1d6db035d85ce..1fe3a41bbcf099f3676d821248cf5e4922622f09 100644
--- a/Sources/PushFeature/PushHandling.swift
+++ b/Sources/PushFeature/PushHandling.swift
@@ -1,70 +1,69 @@
 import UIKit
 
 public protocol PushHandling {
+  /// Submits the APNS token to a 3rd-party service.
+  /// This should be called whenever the user accepts
+  /// receiving remote push notifications.
+  ///
+  /// - Parameters:
+  ///   - token: The APNS provided token
+  ///
+  func registerToken(
+    _ token: Data
+  )
 
-    /// Submits the APNS token to a 3rd-party service.
-    /// This should be called whenever the user accepts
-    /// receiving remote push notifications.
-    ///
-    /// - Parameters:
-    ///   - token: The APNS provided token
-    ///
-    func registerToken(
-        _ token: Data
-    )
+  /// Prompts a system alert to the user requesting
+  /// permission for receiving remote push notifications
+  ///
+  /// - Parameters:
+  ///   - completion: Async result closure containing the user reponse
+  ///
+  func requestAuthorization(
+    _ completion: @escaping (Result<Bool, Error>) -> Void
+  )
 
-    /// Prompts a system alert to the user requesting
-    /// permission for receiving remote push notifications
-    ///
-    /// - Parameters:
-    ///   - completion: Async result closure containing the user reponse
-    ///
-    func requestAuthorization(
-        _ completion: @escaping (Result<Bool, Error>) -> Void
-    )
+  /// Evaluates if the notification should be displayed or not
+  /// and if yes, how should it look like.
+  ///
+  /// - Note: This function should be called by the main app target
+  /// - Warning: The notifications should only appear if the app is in background
+  ///
+  /// - Parameters:
+  ///   - userInfo: Dictionary contaning the payload of the remote push
+  ///   - completion: Async closure containing the operation chosed
+  ///
+  func handlePush(
+    _ userInfo: [AnyHashable: Any],
+    _ completion: @escaping (UIBackgroundFetchResult) -> Void
+  )
 
-    /// Evaluates if the notification should be displayed or not
-    /// and if yes, how should it look like.
-    ///
-    /// - Note: This function should be called by the main app target
-    /// - Warning: The notifications should only appear if the app is in background
-    ///
-    /// - Parameters:
-    ///   - userInfo: Dictionary contaning the payload of the remote push
-    ///   - completion: Async closure containing the operation chosed
-    ///
-    func handlePush(
-        _ userInfo: [AnyHashable: Any],
-        _ completion: @escaping (UIBackgroundFetchResult) -> Void
-    )
+  /// Evaluates if the notification should be displayed or not
+  ///  and if yes, how it should look like and who is it from
+  ///
+  /// - Note: This function should be called by the `NotificationExtension`
+  ///
+  /// - Parameters:
+  ///   - request: The notification request that arrived for the `NotificationExtension`
+  ///   - completion: Async closure containing the operation chosed
+  ///
+  func handlePush(
+    _ request: UNNotificationRequest,
+    _ completion: @escaping (UNNotificationContent) -> Void
+  )
 
-    /// Evaluates if the notification should be displayed or not
-    ///  and if yes, how it should look like and who is it from
-    ///
-    /// - Note: This function should be called by the `NotificationExtension`
-    ///
-    /// - Parameters:
-    ///   - request: The notification request that arrived for the `NotificationExtension`
-    ///   - completion: Async closure containing the operation chosed
-    ///
-    func handlePush(
-        _ request: UNNotificationRequest,
-        _ completion: @escaping (UNNotificationContent) -> Void
-    )
-
-    /// Deeplinks to any UI flow set within the notification.
-    /// It can get called either when the user starts the app
-    /// from a notification or when the user has the app in
-    /// background and resumes the app by tapping on a push
-    ///
-    /// - Parameters:
-    ///   - router: Router instance that will decide the correct UI flow
-    ///   - userInfo: Dictionary contaning the payload of the notification
-    ///   - completion: Async empty closure
-    ///
-    func handleAction(
-        _ router: PushRouter,
-        _ userInfo: [AnyHashable: Any],
-        _ completion: @escaping () -> Void
-    )
+  /// Deeplinks to any UI flow set within the notification.
+  /// It can get called either when the user starts the app
+  /// from a notification or when the user has the app in
+  /// background and resumes the app by tapping on a push
+  ///
+  /// - Parameters:
+  ///   - router: Router instance that will decide the correct UI flow
+  ///   - userInfo: Dictionary contaning the payload of the notification
+  ///   - completion: Async empty closure
+  ///
+  func handleAction(
+    _ router: PushRouter,
+    _ userInfo: [AnyHashable: Any],
+    _ completion: @escaping () -> Void
+  )
 }
diff --git a/Sources/PushFeature/PushRouter.swift b/Sources/PushFeature/PushRouter.swift
index 05885d5196b6025f24d18bd47f5922f1164d1f43..942f747ec8f4df9559d59f12e9a8c3334dacf5ea 100644
--- a/Sources/PushFeature/PushRouter.swift
+++ b/Sources/PushFeature/PushRouter.swift
@@ -1,23 +1,23 @@
 import Foundation
 
 public struct PushRouter {
-    public typealias NavigateTo = (Route, @escaping () -> Void) -> Void
+  public typealias NavigateTo = (Route, @escaping () -> Void) -> Void
 
-    public enum Route {
-        case requests
-        case groupChat(id: Data)
-        case contactChat(id: Data)
-        case search(username: String)
-    }
+  public enum Route {
+    case requests
+    case groupChat(id: Data)
+    case contactChat(id: Data)
+    case search(username: String)
+  }
 
-    public var navigateTo: NavigateTo
+  public var navigateTo: NavigateTo
 
-    public init(navigateTo: @escaping NavigateTo) {
-        self.navigateTo = navigateTo
-    }
+  public init(navigateTo: @escaping NavigateTo) {
+    self.navigateTo = navigateTo
+  }
 }
 
 public extension PushRouter {
-    static let noop = PushRouter { _, _ in }
+  static let noop = PushRouter { _, _ in }
 }
 
diff --git a/Sources/ReportingFeature/Dependency.swift b/Sources/ReportingFeature/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..33e19ae1c98c65fba2b084c9dc0bbf5e10c03c33
--- /dev/null
+++ b/Sources/ReportingFeature/Dependency.swift
@@ -0,0 +1,25 @@
+import Dependencies
+
+private enum ReportingStatusDependencyKey: DependencyKey {
+  static let liveValue: ReportingStatus = .live()
+  static let testValue: ReportingStatus = .unimplemented
+}
+
+extension DependencyValues {
+  public var reportingStatus: ReportingStatus {
+    get { self[ReportingStatusDependencyKey.self] }
+    set { self[ReportingStatusDependencyKey.self] = newValue }
+  }
+}
+  
+private enum SendReportDependencyKey: DependencyKey {
+  static let liveValue: SendReport = .live
+  static let testValue: SendReport = .unimplemented
+}
+
+extension DependencyValues {
+  public var sendReport: SendReport {
+    get { self[SendReportDependencyKey.self] }
+    set { self[SendReportDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/ReportingFeature/FetchBannedList.swift b/Sources/ReportingFeature/FetchBannedList.swift
deleted file mode 100644
index 2620b15c84e5d31316f663a363ff6a4526d1880d..0000000000000000000000000000000000000000
--- a/Sources/ReportingFeature/FetchBannedList.swift
+++ /dev/null
@@ -1,46 +0,0 @@
-import Foundation
-import XCTestDynamicOverlay
-
-public struct FetchBannedList {
-    public enum Error: Swift.Error, Equatable {
-        case network(URLError)
-        case invalidResponse
-    }
-
-    public typealias Completion = (Result<Data, Error>) -> Void
-
-    public var run: (@escaping Completion) -> Void
-
-    public func callAsFunction(completion: @escaping Completion) {
-        run(completion)
-    }
-}
-
-extension FetchBannedList {
-    public static let live = FetchBannedList { completion in
-        let url = URL(string: "https://elixxir-bins.s3.us-west-1.amazonaws.com/client/bannedUsers/banned.csv")!
-        let session = URLSession.shared
-        let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData)
-        let task = session.dataTask(with: request) { data, response, error in
-            if let error = error {
-                completion(.failure(.network(error as! URLError)))
-                return
-            }
-            guard let response = response as? HTTPURLResponse,
-                  (200..<300).contains(response.statusCode),
-                  let data = data
-            else {
-                completion(.failure(.invalidResponse))
-                return
-            }
-            completion(.success(data))
-        }
-        task.resume()
-    }
-}
-
-extension FetchBannedList {
-    public static let unimplemented = FetchBannedList(
-        run: XCTUnimplemented("\(Self.self)")
-    )
-}
diff --git a/Sources/ReportingFeature/MakeAppScreenshot.swift b/Sources/ReportingFeature/MakeAppScreenshot.swift
index 7d44af879f35d792685f3e278cc6ce9c044d8a07..75a1fc31e6139e9a3fc2510eb811f00ffe37a628 100644
--- a/Sources/ReportingFeature/MakeAppScreenshot.swift
+++ b/Sources/ReportingFeature/MakeAppScreenshot.swift
@@ -3,51 +3,51 @@ import UIKit
 import XCTestDynamicOverlay
 
 public struct MakeAppScreenshot {
-    public enum Error: Swift.Error, Equatable {
-        case unableToGetForegroundWindowScene
-        case unableToGetKeyWindow
-    }
-
-    public var run: () throws -> UIImage
-
-    public func callAsFunction() throws -> UIImage {
-        try run()
-    }
+  public enum Error: Swift.Error, Equatable {
+    case unableToGetForegroundWindowScene
+    case unableToGetKeyWindow
+  }
+  
+  public var run: () throws -> UIImage
+  
+  public func callAsFunction() throws -> UIImage {
+    try run()
+  }
 }
 
 extension MakeAppScreenshot {
-    public static let live = MakeAppScreenshot {
-        let scene: UIWindowScene? = UIApplication.shared.connectedScenes
-            .filter { $0.activationState == .foregroundActive }
-            .compactMap { $0 as? UIWindowScene }
-            .first
-
-        guard let scene = scene else {
-            throw Error.unableToGetForegroundWindowScene
-        }
-
-        let window: UIWindow? = scene.windows.first(where: \.isKeyWindow)
-
-        guard let keyWindow = window else {
-            throw Error.unableToGetKeyWindow
-        }
-
-        let rendererFormat = UIGraphicsImageRendererFormat()
-        rendererFormat.scale = scene.screen.scale
-
-        let renderer = UIGraphicsImageRenderer(
-            bounds: keyWindow.bounds,
-            format: rendererFormat
-        )
-
-        return renderer.image { ctx in
-            keyWindow.layer.render(in: ctx.cgContext)
-        }
+  public static let live = MakeAppScreenshot {
+    let scene: UIWindowScene? = UIApplication.shared.connectedScenes
+      .filter { $0.activationState == .foregroundActive }
+      .compactMap { $0 as? UIWindowScene }
+      .first
+    
+    guard let scene = scene else {
+      throw Error.unableToGetForegroundWindowScene
+    }
+    
+    let window: UIWindow? = scene.windows.first(where: \.isKeyWindow)
+    
+    guard let keyWindow = window else {
+      throw Error.unableToGetKeyWindow
     }
+    
+    let rendererFormat = UIGraphicsImageRendererFormat()
+    rendererFormat.scale = scene.screen.scale
+    
+    let renderer = UIGraphicsImageRenderer(
+      bounds: keyWindow.bounds,
+      format: rendererFormat
+    )
+    
+    return renderer.image { ctx in
+      keyWindow.layer.render(in: ctx.cgContext)
+    }
+  }
 }
 
 extension MakeAppScreenshot {
-    public static let unimplemented = MakeAppScreenshot(
-        run: XCTUnimplemented("\(Self.self)")
-    )
+  public static let unimplemented = MakeAppScreenshot(
+    run: XCTUnimplemented("\(Self.self)")
+  )
 }
diff --git a/Sources/ReportingFeature/ProcessBannedList.swift b/Sources/ReportingFeature/ProcessBannedList.swift
deleted file mode 100644
index 3399a34ee3614bc41df393251d1e21a9309cdf52..0000000000000000000000000000000000000000
--- a/Sources/ReportingFeature/ProcessBannedList.swift
+++ /dev/null
@@ -1,64 +0,0 @@
-import Foundation
-import SwiftCSV
-import XCTestDynamicOverlay
-
-public struct ProcessBannedList {
-    public enum ElementError: Swift.Error {
-        case missingUserId
-        case invalidUserId(String)
-    }
-
-    public enum Error: Swift.Error {
-        case invalidData
-        case csv(Swift.Error)
-    }
-
-    public typealias ForEach = (Result<Data, ElementError>) -> Void
-    public typealias Completion = (Result<Void, Error>) -> Void
-
-    public var run: (Data, ForEach, Completion) -> Void
-
-    public func callAsFunction(
-        data: Data,
-        forEach: ForEach,
-        completion: Completion
-    ) {
-        run(data, forEach, completion)
-    }
-}
-
-extension ProcessBannedList {
-    public static let live = ProcessBannedList { data, forEach, completion in
-        guard let csvString = String(data: data, encoding: .utf8) else {
-            completion(.failure(.invalidData))
-            return
-        }
-        let csv: EnumeratedCSV
-        do {
-            csv = try EnumeratedCSV(string: csvString)
-        }
-        catch {
-            completion(.failure(.csv(error)))
-            return
-        }
-        csv.rows.forEach { row in
-            guard let userIdString = row.first else {
-                forEach(.failure(.missingUserId))
-                return
-            }
-            guard let userId = Data(base64Encoded: userIdString) else {
-                forEach(.failure(.invalidUserId(userIdString)))
-                return
-            }
-            forEach(.success(userId))
-        }
-        completion(.success(()))
-    }
-}
-
-extension ProcessBannedList {
-    public static let unimplemented = ProcessBannedList { _, _, _ in
-        let run: () -> Void = XCTUnimplemented("\(Self.self)")
-        run()
-    }
-}
diff --git a/Sources/ReportingFeature/Report.swift b/Sources/ReportingFeature/Report.swift
index c2032b6a6b87d096f8f6883085d4c6e887630600..56ff6192eeee64004e4cb5a3b5d978017d719998 100644
--- a/Sources/ReportingFeature/Report.swift
+++ b/Sources/ReportingFeature/Report.swift
@@ -1,52 +1,52 @@
 import Foundation
 
 public struct Report: Encodable {
-    public init(
-        sender: ReportUser,
-        recipient: ReportUser,
-        type: ReportType,
-        screenshot: Data,
-        partyName: String? = nil,
-        partyBlob: String? = nil,
-        partyMembers: [ReportUser]? = nil
-    ) {
-        self.sender = sender
-        self.recipient = recipient
-        self.type = type
-        self.screenshot = screenshot
-        self.partyName = partyName
-        self.partyBlob = partyBlob
-        self.partyMembers = partyMembers
-    }
-
-    public var sender: ReportUser
-    public var recipient: ReportUser
-    public var type: ReportType
-    public var screenshot: Data
-    public var partyName: String?
-    public var partyBlob: String?
-    public var partyMembers: [ReportUser]?
+  public init(
+    sender: ReportUser,
+    recipient: ReportUser,
+    type: ReportType,
+    screenshot: Data,
+    partyName: String? = nil,
+    partyBlob: String? = nil,
+    partyMembers: [ReportUser]? = nil
+  ) {
+    self.sender = sender
+    self.recipient = recipient
+    self.type = type
+    self.screenshot = screenshot
+    self.partyName = partyName
+    self.partyBlob = partyBlob
+    self.partyMembers = partyMembers
+  }
+  
+  public var sender: ReportUser
+  public var recipient: ReportUser
+  public var type: ReportType
+  public var screenshot: Data
+  public var partyName: String?
+  public var partyBlob: String?
+  public var partyMembers: [ReportUser]?
 }
 
 extension Report {
-    public struct ReportUser: Encodable {
-        public init(
-            userId: String,
-            username: String
-        ) {
-            self.userId = userId
-            self.username = username
-        }
-
-        public var userId: String
-        public var username: String
+  public struct ReportUser: Encodable {
+    public init(
+      userId: String,
+      username: String
+    ) {
+      self.userId = userId
+      self.username = username
     }
+    
+    public var userId: String
+    public var username: String
+  }
 }
 
 extension Report {
-    public enum ReportType: String, Encodable {
-        case dm
-        case group
-        case channel
-    }
+  public enum ReportType: String, Encodable {
+    case dm
+    case group
+    case channel
+  }
 }
diff --git a/Sources/ReportingFeature/ReportingStatus.swift b/Sources/ReportingFeature/ReportingStatus.swift
index f6346ce1350caa9bca8ead86515724a5edf7171d..2da0592e647cc059be8d2152e72a4e71c81d5689 100644
--- a/Sources/ReportingFeature/ReportingStatus.swift
+++ b/Sources/ReportingFeature/ReportingStatus.swift
@@ -20,14 +20,14 @@ extension ReportingStatus {
         if isOptional.get() == false {
           return true
         }
-
+        
         return isEnabled.get()
       },
       isEnabledPublisher: {
         if isOptional.get() == false {
           return Just(true).eraseToAnyPublisher()
         }
-
+        
         return isEnabled.publisher()
       },
       enable: { enabled in
@@ -35,7 +35,7 @@ extension ReportingStatus {
       }
     )
   }
-
+  
   public static func mock(
     isEnabled: Bool = false,
     isOptional: Bool = true
@@ -48,4 +48,11 @@ extension ReportingStatus {
       enable: { isEnabledSubject.send($0) }
     )
   }
+
+  public static let unimplemented = ReportingStatus(
+    isOptional: { fatalError() },
+    isEnabled: { fatalError() },
+    isEnabledPublisher: { fatalError() },
+    enable: { _ in }
+  )
 }
diff --git a/Sources/ReportingFeature/ReportingStatusIsEnabled.swift b/Sources/ReportingFeature/ReportingStatusIsEnabled.swift
index 32f23fcb78a3b5e8fe7f6dc15a95a1b27e278bfb..ecf02aba50fff9f2334ad50dee4a6d2b8aa2dbb8 100644
--- a/Sources/ReportingFeature/ReportingStatusIsEnabled.swift
+++ b/Sources/ReportingFeature/ReportingStatusIsEnabled.swift
@@ -2,37 +2,37 @@ import Combine
 import Foundation
 
 public struct ReportingStatusIsEnabled {
-    public var get: () -> Bool
-    public var set: (Bool) -> Void
-    public var publisher: () -> AnyPublisher<Bool, Never>
+  public var get: () -> Bool
+  public var set: (Bool) -> Void
+  public var publisher: () -> AnyPublisher<Bool, Never>
 }
 
 extension ReportingStatusIsEnabled {
-    public static func live(
-        userDefaults: UserDefaults = .standard
-    ) -> ReportingStatusIsEnabled {
-        ReportingStatusIsEnabled(
-            get: {
-                userDefaults.isReportingEnabled
-            },
-            set: { enabled in
-                userDefaults.isReportingEnabled = enabled
-            },
-            publisher: {
-                userDefaults.publisher(for: \.isReportingEnabled).eraseToAnyPublisher()
-            }
-        )
-    }
+  public static func live(
+    userDefaults: UserDefaults = .standard
+  ) -> ReportingStatusIsEnabled {
+    ReportingStatusIsEnabled(
+      get: {
+        userDefaults.isReportingEnabled
+      },
+      set: { enabled in
+        userDefaults.isReportingEnabled = enabled
+      },
+      publisher: {
+        userDefaults.publisher(for: \.isReportingEnabled).eraseToAnyPublisher()
+      }
+    )
+  }
 }
 
 private extension UserDefaults {
-    static let isReportingEnabledKey = "isReportingEnabled"
-
-    @objc var isReportingEnabled: Bool {
-        get {
-            bool(forKey: Self.isReportingEnabledKey)
-        } set {
-            set(newValue, forKey: Self.isReportingEnabledKey)
-        }
+  static let isReportingEnabledKey = "isReportingEnabled"
+  
+  @objc var isReportingEnabled: Bool {
+    get {
+      bool(forKey: Self.isReportingEnabledKey)
+    } set {
+      set(newValue, forKey: Self.isReportingEnabledKey)
     }
+  }
 }
diff --git a/Sources/ReportingFeature/ReportingStatusIsOptional.swift b/Sources/ReportingFeature/ReportingStatusIsOptional.swift
index e0cc6591bf1d13c68d022a2f8587cc495403f89d..ca5ad5654ba72678496581b7ac3aae56626bc577 100644
--- a/Sources/ReportingFeature/ReportingStatusIsOptional.swift
+++ b/Sources/ReportingFeature/ReportingStatusIsOptional.swift
@@ -1,24 +1,24 @@
 import Foundation
 
 public struct ReportingStatusIsOptional {
-    public var get: () -> Bool
+  public var get: () -> Bool
 }
 
 extension ReportingStatusIsOptional {
-    public static func live(
-        plist url: URL = Bundle.main.url(forResource: "Info", withExtension: "plist")!
-    ) -> ReportingStatusIsOptional {
-        ReportingStatusIsOptional {
-            struct Plist: Decodable {
-                let isReportingOptional: Bool
-            }
-
-            guard let data = try? Data(contentsOf: url),
-                  let infoPlist = try? PropertyListDecoder().decode(Plist.self, from: data) else {
-                return true
-            }
-
-            return infoPlist.isReportingOptional
-        }
+  public static func live(
+    plist url: URL = Bundle.main.url(forResource: "Info", withExtension: "plist")!
+  ) -> ReportingStatusIsOptional {
+    ReportingStatusIsOptional {
+      struct Plist: Decodable {
+        let isReportingOptional: Bool
+      }
+      
+      guard let data = try? Data(contentsOf: url),
+            let infoPlist = try? PropertyListDecoder().decode(Plist.self, from: data) else {
+        return true
+      }
+      
+      return infoPlist.isReportingOptional
     }
+  }
 }
diff --git a/Sources/ReportingFeature/SendReport.swift b/Sources/ReportingFeature/SendReport.swift
index 4793d998d49c43426012ac9760cd28e39e8eb8e6..678bfbc3d1ce2a8339975e74b56330591b6ff06d 100644
--- a/Sources/ReportingFeature/SendReport.swift
+++ b/Sources/ReportingFeature/SendReport.swift
@@ -2,93 +2,93 @@ import Foundation
 import XCTestDynamicOverlay
 
 public struct SendReport {
-    public typealias Completion = (Result<Void, Error>) -> Void
+  public typealias Completion = (Result<Void, Error>) -> Void
 
-    public var run: (Report, @escaping Completion) -> Void
+  public var run: (Report, @escaping Completion) -> Void
 
-    public func callAsFunction(_ report: Report, completion: @escaping Completion) {
-        run(report, completion)
-    }
+  public func callAsFunction(_ report: Report, completion: @escaping Completion) {
+    run(report, completion)
+  }
 }
 
 extension SendReport {
-    public static let live = SendReport { report, completion in
-        let url = URL(string: "https://3.74.237.181:11420/report")!
-        var request = URLRequest(url: url)
-        request.httpMethod = "POST"
-        do {
-            request.httpBody = try JSONEncoder().encode(report)
-        } catch {
-            completion(.failure(error))
-            return
-        }
-        let session = URLSession(
-            configuration: .default,
-            delegate: SessionDelegate(),
-            delegateQueue: nil
-        )
-        let task = session.dataTask(with: request) { _, _, error in
-            defer { session.invalidateAndCancel() }
-            if let error = error {
-                completion(.failure(error))
-                return
-            }
-            completion(.success(()))
-        }
-        task.resume()
+  public static let live = SendReport { report, completion in
+    let url = URL(string: "https://3.74.237.181:11420/report")!
+    var request = URLRequest(url: url)
+    request.httpMethod = "POST"
+    do {
+      request.httpBody = try JSONEncoder().encode(report)
+    } catch {
+      completion(.failure(error))
+      return
+    }
+    let session = URLSession(
+      configuration: .default,
+      delegate: SessionDelegate(),
+      delegateQueue: nil
+    )
+    let task = session.dataTask(with: request) { _, _, error in
+      defer { session.invalidateAndCancel() }
+      if let error = error {
+        completion(.failure(error))
+        return
+      }
+      completion(.success(()))
     }
+    task.resume()
+  }
 
-    public static func mock(
-        result: Result<Void, Error> = .success(())
-    ) -> SendReport {
-        SendReport { report, completion in
-            print("[SendReport.mock] Sending report: \(report)")
-            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
-                print("[SendReport.mock] Sending report finished")
-                completion(result)
-            }
-        }
+  public static func mock(
+    result: Result<Void, Error> = .success(())
+  ) -> SendReport {
+    SendReport { report, completion in
+      print("[SendReport.mock] Sending report: \(report)")
+      DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
+        print("[SendReport.mock] Sending report finished")
+        completion(result)
+      }
     }
+  }
 }
 
 extension SendReport {
-    public static let unimplemented = SendReport(
-        run: XCTUnimplemented("\(Self.self)")
-    )
+  public static let unimplemented = SendReport(
+    run: XCTUnimplemented("\(Self.self)")
+  )
 }
 
 private final class SessionDelegate: NSObject, URLSessionDelegate {
-    func urlSession(
-        _ session: URLSession,
-        didReceive challenge: URLAuthenticationChallenge,
-        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
-    ) {
-        let authMethod = challenge.protectionSpace.authenticationMethod
-        guard authMethod == NSURLAuthenticationMethodServerTrust else {
-            return completionHandler(.cancelAuthenticationChallenge, nil)
-        }
-
-        guard let serverTrust = challenge.protectionSpace.serverTrust else {
-            return completionHandler(.cancelAuthenticationChallenge, nil)
-        }
+  func urlSession(
+    _ session: URLSession,
+    didReceive challenge: URLAuthenticationChallenge,
+    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void
+  ) {
+    let authMethod = challenge.protectionSpace.authenticationMethod
+    guard authMethod == NSURLAuthenticationMethodServerTrust else {
+      return completionHandler(.cancelAuthenticationChallenge, nil)
+    }
 
-        guard let serverCert = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
-            return completionHandler(.cancelAuthenticationChallenge, nil)
-        }
+    guard let serverTrust = challenge.protectionSpace.serverTrust else {
+      return completionHandler(.cancelAuthenticationChallenge, nil)
+    }
 
-        let serverCertCFData = SecCertificateCopyData(serverCert)
-        let serverCertData = Data(
-            bytes: CFDataGetBytePtr(serverCertCFData),
-            count: CFDataGetLength(serverCertCFData)
-        )
+    guard let serverCert = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
+      return completionHandler(.cancelAuthenticationChallenge, nil)
+    }
 
-        let localCertURL = Bundle.module.url(forResource: "report_cert", withExtension: "der")!
-        let localCertData = try! Data(contentsOf: localCertURL)
+    let serverCertCFData = SecCertificateCopyData(serverCert)
+    let serverCertData = Data(
+      bytes: CFDataGetBytePtr(serverCertCFData),
+      count: CFDataGetLength(serverCertCFData)
+    )
 
-        guard serverCertData == localCertData else {
-            return completionHandler(.cancelAuthenticationChallenge, nil)
-        }
+    let localCertURL = Bundle.module.url(forResource: "report_cert", withExtension: "der")!
+    let localCertData = try! Data(contentsOf: localCertURL)
 
-        completionHandler(.useCredential, URLCredential(trust: serverTrust))
+    guard serverCertData == localCertData else {
+      return completionHandler(.cancelAuthenticationChallenge, nil)
     }
+
+    completionHandler(.useCredential, URLCredential(trust: serverTrust))
+  }
 }
diff --git a/Sources/RequestPermissionFeature/RequestPermissionController.swift b/Sources/RequestPermissionFeature/RequestPermissionController.swift
index 2a8e364d2315742f0e0d674549830ac9a9778744..9c12752c92e20763c81647fe501e749d014eca3e 100644
--- a/Sources/RequestPermissionFeature/RequestPermissionController.swift
+++ b/Sources/RequestPermissionFeature/RequestPermissionController.swift
@@ -1,13 +1,14 @@
 import UIKit
 import Shared
 import Combine
+import AppCore
+import Dependencies
 import AppResources
-import StatusBarFeature
+import AppNavigation
 import PermissionsFeature
-import ComposableArchitecture
 
 public final class RequestPermissionController: UIViewController {
-  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
   @Dependency(\.permissions) var permissions: PermissionsManager
 
   private lazy var screenView = RequestPermissionView()
@@ -28,7 +29,7 @@ public final class RequestPermissionController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    statusBar.update(.darkContent)
+    statusBar.set(.darkContent)
   }
 
   public override func viewDidLoad() {
diff --git a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
index 97615508af52356b838b25614e59dc15d29da2b6..11a4270c77ca96b452a2bbbcc1fcb2d3f9df560f 100644
--- a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import AppResources
+import Dependencies
+import AppNavigation
 import ContactFeature
-import DI
 
 public final class RequestsContainerController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = RequestsContainerView()
   private var cancellables = Set<AnyCancellable>()
@@ -29,7 +31,7 @@ public final class RequestsContainerController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
 
     navigationController?.navigationBar
       .customize(backgroundColor: Asset.neutralWhite.color)
diff --git a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
index 7f3f63fa70018e906325f7129a92711331bb0a09..a7e65e87d510deaac71d9a0b3a2024c8d58f99b3 100644
--- a/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsFailedController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Combine
-import DI
 
 final class RequestsFailedController: UIViewController {
     private lazy var screenView = RequestsFailedView()
diff --git a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
index 674e3bd10232c2d4e615200526e4c5ebe1c2264b..3ee84bb9e1b29b539448cb11e222fbcf3c452ce8 100644
--- a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
@@ -2,14 +2,16 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import Navigation
+import AppCore
+import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
 import CountryListFeature
-import DI
 
 final class RequestsReceivedController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var toaster: ToastController
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.toastManager) var toaster: ToastManager
 
   private lazy var screenView = RequestsReceivedView()
   private var cancellables = Set<AnyCancellable>()
@@ -265,7 +267,7 @@ extension RequestsReceivedController {
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self else { return }
           self.drawerCancellables.removeAll()
-          self.navigator.perform(PresentChat(contact: contact, on: navigationController!))
+          self.navigator.perform(PresentChat(contact: contact, on: self.navigationController!))
         }
       }.store(in: &drawerCancellables)
 
diff --git a/Sources/RequestsFeature/Controllers/RequestsSentController.swift b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
index 25a35aae40e1a0d673827ac39876192c79e18329..a2000f74cd532e7c90f404c79e1f4225ea919a7f 100644
--- a/Sources/RequestsFeature/Controllers/RequestsSentController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsSentController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Combine
-import DI
 
 final class RequestsSentController: UIViewController {
     var connectionsPublisher: AnyPublisher<Void, Never> {
diff --git a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
index 5354509e3df44e0b63b05211338751535ae8c15b..6481b67c4a5c25a148980b6a3ed2d454d61f7822 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsFailedViewModel.swift
@@ -1,17 +1,18 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import XXModels
 import Defaults
 import XXClient
+import Dependencies
 import CombineSchedulers
-import DI
 import XXMessengerClient
 
 final class RequestsFailedViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
   
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool
@@ -27,7 +28,7 @@ final class RequestsFailedViewModel {
   var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
   
   init() {
-    database.fetchContactsPublisher(.init(authStatus: [.requestFailed, .confirmationFailed]))
+    try! dbManager.getDB().fetchContactsPublisher(.init(authStatus: [.requestFailed, .confirmationFailed]))
       .replaceError(with: [])
       .map { data -> NSDiffableDataSourceSnapshot<Section, Request> in
         var snapshot = NSDiffableDataSourceSnapshot<Section, Request>()
@@ -45,7 +46,7 @@ final class RequestsFailedViewModel {
       return
     }
     
-    hudController.show()
+    hudManager.show()
     backgroundScheduler.schedule { [weak self] in
       guard let self else { return }
       
@@ -81,11 +82,11 @@ final class RequestsFailedViewModel {
           contact.authStatus = .friend
         }
         
-        try self.database.saveContact(contact)
-        self.hudController.dismiss()
+        try self.dbManager.getDB().saveContact(contact)
+        self.hudManager.hide()
       } catch {
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.hudManager.show(.init(content: xxError))
       }
     }
   }
diff --git a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
index 466050340082d44c5bb768c3cd02e7011c6671ca..eb8469c67044a3cb962927a389da2831eb56ee4b 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsReceivedViewModel.swift
@@ -1,13 +1,14 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import Defaults
 import XXModels
 import XXClient
+import Dependencies
 import DrawerFeature
 import ReportingFeature
 import CombineSchedulers
-import DI
 import XXMessengerClient
 
 import struct XXModels.Group
@@ -19,11 +20,12 @@ struct RequestReceived: Hashable, Equatable {
 }
 
 final class RequestsReceivedViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var groupManager: GroupChat
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  //@Dependency var groupManager: GroupChat
   
   @KeyObject(.isShowingHiddenRequests, defaultValue: false) var isShowingHiddenRequests: Bool
 
@@ -74,11 +76,11 @@ final class RequestsReceivedViewModel {
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
     
-    let groupStream = database
+    let groupStream = try! dbManager.getDB()
       .fetchGroupsPublisher(groupsQuery)
       .replaceError(with: [])
     
-    let contactsStream = database
+    let contactsStream = try! dbManager.getDB()
       .fetchContactsPublisher(contactsQuery)
       .replaceError(with: [])
     
@@ -151,7 +153,7 @@ final class RequestsReceivedViewModel {
         
         do {
           contact.authStatus = .verificationInProgress
-          try self.database.saveContact(contact)
+          try self.dbManager.getDB().saveContact(contact)
           
           print(">>> [messenger.verifyContact] will start")
           
@@ -159,17 +161,17 @@ final class RequestsReceivedViewModel {
             print(">>> [messenger.verifyContact] verified")
             
             contact.authStatus = .verified
-            contact = try self.database.saveContact(contact)
+            contact = try self.dbManager.getDB().saveContact(contact)
           } else {
             print(">>> [messenger.verifyContact] is fake")
             
-            try self.database.deleteContact(contact)
+            try self.dbManager.getDB().deleteContact(contact)
           }
         } catch {
           print(">>> [messenger.verifyContact] thrown an exception: \(error.localizedDescription)")
           
           contact.authStatus = .verificationFailed
-          _ = try? self.database.saveContact(contact)
+          _ = try? self.dbManager.getDB().saveContact(contact)
         }
       }
     } else if request.status == .verifying {
@@ -178,29 +180,29 @@ final class RequestsReceivedViewModel {
   }
   
   func didRequestHide(group: Group) {
-    if var group = try? database.fetchGroups(.init(id: [group.id])).first {
+    if var group = try? dbManager.getDB().fetchGroups(.init(id: [group.id])).first {
       group.authStatus = .hidden
-      _ = try? database.saveGroup(group)
+      _ = try? dbManager.getDB().saveGroup(group)
     }
   }
   
   func didRequestAccept(group: Group) {
-    hudController.show()
+    hudManager.show()
     
     backgroundScheduler.schedule { [weak self] in
       guard let self else { return }
       
       do {
-        try self.groupManager.joinGroup(serializedGroupData: group.serialized)
+        //try self.groupManager.joinGroup(serializedGroupData: group.serialized)
         
         var group = group
         group.authStatus = .participating
-        try self.database.saveGroup(group)
+        try self.dbManager.getDB().saveGroup(group)
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.groupConfirmationSubject.send(group)
       } catch {
-        self.hudController.show(.init(error: error))
+        self.hudManager.show(.init(error: error))
       }
     }
   }
@@ -209,8 +211,8 @@ final class RequestsReceivedViewModel {
     _ group: Group,
     _ completion: @escaping (Result<[DrawerTableCellModel], Error>) -> Void
   ) {
-    if let info = try? database.fetchGroupInfos(.init(groupId: group.id)).first {
-      database.fetchContactsPublisher(.init(id: Set(info.members.map(\.id))))
+    if let info = try? dbManager.getDB().fetchGroupInfos(.init(groupId: group.id)).first {
+      try! dbManager.getDB().fetchContactsPublisher(.init(id: Set(info.members.map(\.id))))
         .replaceError(with: [])
         .sink { members in
           let withUsername = members
@@ -243,14 +245,14 @@ final class RequestsReceivedViewModel {
   }
   
   func didRequestHide(contact: XXModels.Contact) {
-    if var contact = try? database.fetchContacts(.init(id: [contact.id])).first {
+    if var contact = try? dbManager.getDB().fetchContacts(.init(id: [contact.id])).first {
       contact.authStatus = .hidden
-      _ = try? database.saveContact(contact)
+      _ = try? dbManager.getDB().saveContact(contact)
     }
   }
   
   func didRequestAccept(contact: XXModels.Contact, nickname: String? = nil) {
-    hudController.show()
+    hudManager.show()
     
     var contact = contact
     contact.authStatus = .confirming
@@ -260,24 +262,24 @@ final class RequestsReceivedViewModel {
       guard let self else { return }
       
       do {
-        try self.database.saveContact(contact)
+        try self.dbManager.getDB().saveContact(contact)
         
         let _ = try self.messenger.e2e.get()!.confirmReceivedRequest(partner: .live(contact.marshaled!))
         contact.authStatus = .friend
-        try self.database.saveContact(contact)
+        try self.dbManager.getDB().saveContact(contact)
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.contactConfirmationSubject.send(contact)
       } catch {
         contact.authStatus = .confirmationFailed
-        _ = try? self.database.saveContact(contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
   
   func groupChatWith(group: Group) -> GroupInfo {
-    guard let info = try? database.fetchGroupInfos(.init(groupId: group.id)).first else {
+    guard let info = try? dbManager.getDB().fetchGroupInfos(.init(groupId: group.id)).first else {
       fatalError()
     }
     
diff --git a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
index c527b0fbad997b09309e458ffe0df638b049bf65..abe6ba7b6c2e20c14115ce6f54535f841c693930 100644
--- a/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
+++ b/Sources/RequestsFeature/ViewModels/RequestsSentViewModel.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import Defaults
 import XXModels
 import Defaults
 import XXClient
+import AppResources
+import Dependencies
 import ReportingFeature
 import CombineSchedulers
-import DI
 import XXMessengerClient
 
 struct RequestSent: Hashable, Equatable {
@@ -16,11 +18,11 @@ struct RequestSent: Hashable, Equatable {
 }
 
 final class RequestsSentViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var toastController: ToastController
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.toastManager) var toastManager: ToastManager
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
   
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool
@@ -45,7 +47,7 @@ final class RequestsSentViewModel {
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
     
-    database.fetchContactsPublisher(query)
+    try! dbManager.getDB().fetchContactsPublisher(query)
       .replaceError(with: [])
       .removeDuplicates()
       .map { data -> NSDiffableDataSourceSnapshot<Section, RequestSent> in
@@ -67,7 +69,7 @@ final class RequestsSentViewModel {
     
     let name = (contact.nickname ?? contact.username) ?? ""
     
-    hudController.show()
+    hudManager.show()
     backgroundScheduler.schedule { [weak self] in
       guard let self else { return }
       
@@ -92,7 +94,7 @@ final class RequestsSentViewModel {
           myFacts: includedFacts
         )
         
-        self.hudController.dismiss()
+        self.hudManager.hide()
         
         var item = item
         var allRequests = self.itemsSubject.value.itemIdentifiers
@@ -104,7 +106,7 @@ final class RequestsSentViewModel {
         item.isResent = true
         allRequests.append(item)
         
-        self.toastController.enqueueToast(model: .init(
+        self.toastManager.enqueue(.init(
           title: Localized.Requests.Sent.Toast.resent(name),
           leftImage: Asset.requestSentToaster.image
         ))
@@ -114,13 +116,13 @@ final class RequestsSentViewModel {
         snapshot.appendItems(allRequests, toSection: .appearing)
         self.itemsSubject.send(snapshot)
       } catch {
-        self.toastController.enqueueToast(model: .init(
+        self.toastManager.enqueue(.init(
           title: Localized.Requests.Sent.Toast.resentFailed(name),
           leftImage: Asset.requestFailedToaster.image
         ))
         
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-        self.hudController.show(.init(content: xxError))
+        self.hudManager.show(.init(content: xxError))
       }
     }
   }
diff --git a/Sources/RequestsFeature/Views/RequestCell.swift b/Sources/RequestsFeature/Views/RequestCell.swift
index c1c81d28222654804ad1b0332608ce807c080c9d..217e969783cff7cfe659711861ebee6a5ef51d99 100644
--- a/Sources/RequestsFeature/Views/RequestCell.swift
+++ b/Sources/RequestsFeature/Views/RequestCell.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 import CountryListFeature
 
 final class RequestCell: UICollectionViewCell {
diff --git a/Sources/RequestsFeature/Views/RequestCellButton.swift b/Sources/RequestsFeature/Views/RequestCellButton.swift
index b876ba691252c0a938ea40e162856a4102fb0ae2..005197063e8220863d70edec1cfc1c9a5e93bf5c 100644
--- a/Sources/RequestsFeature/Views/RequestCellButton.swift
+++ b/Sources/RequestsFeature/Views/RequestCellButton.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestCellButton: UIControl {
   let titleLabel = UILabel()
diff --git a/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift b/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
index 574d63b624404285a5c1310706453bbd2f0b8d63..4239feca2ff52a7db5573e39b3dca1bff438bbe1 100644
--- a/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
+++ b/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestReceivedEmptyCell: UICollectionViewCell {
   private let titleLabel = UILabel()
diff --git a/Sources/RequestsFeature/Views/RequestSegmentedButton.swift b/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
index 36077491610b6f25bddebd8bc5801058c4d634ca..85f49138de97d52b9551ed2f8a659ddf562a9565 100644
--- a/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
+++ b/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestSegmentedButton: UIControl {
   let titleLabel = UILabel()
diff --git a/Sources/RequestsFeature/Views/RequestsContainerView.swift b/Sources/RequestsFeature/Views/RequestsContainerView.swift
index a5188d080d1773a256ffb06cc6b8f7376c243f2b..222a9eb74e6ac3075d63fe34d6917db8bb6cc4d3 100644
--- a/Sources/RequestsFeature/Views/RequestsContainerView.swift
+++ b/Sources/RequestsFeature/Views/RequestsContainerView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestsContainerView: UIView {
   let scrollView = UIScrollView()
diff --git a/Sources/RequestsFeature/Views/RequestsFailedView.swift b/Sources/RequestsFeature/Views/RequestsFailedView.swift
index 86d76dc764f89478da0c6b4df19b02c95b02ebd4..b3ded76b653c0d8053e5476f42f0c1bfb62b9c08 100644
--- a/Sources/RequestsFeature/Views/RequestsFailedView.swift
+++ b/Sources/RequestsFeature/Views/RequestsFailedView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestsFailedView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift b/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
index 7a8aed798d0c459ce1dd48c028ff12a23dab195f..9442a7a55097f411933b048522893da51afb0763 100644
--- a/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
+++ b/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class RequestsHiddenSectionHeader: UICollectionReusableView {
   let titleLabel = UILabel()
diff --git a/Sources/RequestsFeature/Views/RequestsReceivedView.swift b/Sources/RequestsFeature/Views/RequestsReceivedView.swift
index f8c55b664deabb2c5bc0cff54e2246d048907f6b..5e60e04ac94f513c3e96018e2dd3762fedb8ca56 100644
--- a/Sources/RequestsFeature/Views/RequestsReceivedView.swift
+++ b/Sources/RequestsFeature/Views/RequestsReceivedView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestsReceivedView: UIView {
   lazy var collectionView: UICollectionView = {
diff --git a/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift b/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
index d58fbf874ba461f7ee112732fd88c8fed8075a30..6467704207b98661ee3158a471264bb073b1aa01 100644
--- a/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
+++ b/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import SnapKit
+import AppResources
 
 final class RequestsSegmentedControl: UIView {
   private let trackView = UIView()
diff --git a/Sources/RequestsFeature/Views/RequestsSentView.swift b/Sources/RequestsFeature/Views/RequestsSentView.swift
index 6c65a92b91b99464a4a1d7e3210ff655465987ba..1035850ca0165d44893bef7fc3750c0679ee6bcf 100644
--- a/Sources/RequestsFeature/Views/RequestsSentView.swift
+++ b/Sources/RequestsFeature/Views/RequestsSentView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RequestsSentView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/RestoreFeature/Controllers/RestoreController.swift b/Sources/RestoreFeature/Controllers/RestoreController.swift
index a58bdd1f8200c759660ec8398337dcf50c6a42fb..ac6f6ae1b3778411c35f750734fe2498371e3f90 100644
--- a/Sources/RestoreFeature/Controllers/RestoreController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreController.swift
@@ -1,13 +1,13 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import Navigation
 import AppResources
+import AppNavigation
 import DrawerFeature
+import ComposableArchitecture
 
 public final class RestoreController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = RestoreView()
 
@@ -56,8 +56,9 @@ public final class RestoreController: UIViewController {
       .sink { [unowned self] in
         screenView.updateFor(step: $0)
         if $0 == .wrongPass {
-          navigator.perform(PresentPassphrase(onCancel: {
-            navigator.perform(DismissModal(from: self))
+          navigator.perform(PresentPassphrase(onCancel: { [weak self] in
+            guard let self else { return }
+            self.navigator.perform(DismissModal(from: self))
           }, onPassphrase: { [weak self] passphrase in
             guard let self else { return }
             self.viewModel.retryWith(passphrase: passphrase)
@@ -87,8 +88,9 @@ public final class RestoreController: UIViewController {
       .restoreButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentPassphrase(onCancel: {
-          navigator.perform(DismissModal(from: self))
+        navigator.perform(PresentPassphrase(onCancel: { [weak self] in
+          guard let self else { return }
+          self.navigator.perform(DismissModal(from: self))
         }, onPassphrase: { [weak self] passphrase in
           guard let self else { return }
           self.viewModel.didTapRestore(passphrase: passphrase)
diff --git a/Sources/RestoreFeature/Controllers/RestoreListController.swift b/Sources/RestoreFeature/Controllers/RestoreListController.swift
index 14fdc78eb0ec8ba4dc1787ac002a3c799f38ba99..cbce48e53d9b5943a84495906dfd64cc38bfd484 100644
--- a/Sources/RestoreFeature/Controllers/RestoreListController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreListController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
+import ComposableArchitecture
 
 public final class RestoreListController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = RestoreListView()
 
diff --git a/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift b/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
index 45bd32d7d3c8f6a5c252c2f9c5ae54767eb5ee27..660287c6ca004e36beb04bfeb60a4ad839f55e1f 100644
--- a/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
+++ b/Sources/RestoreFeature/Controllers/RestorePassphraseController.swift
@@ -17,13 +17,13 @@ public final class RestorePassphraseController: UIViewController {
     }
   }
 
-  private let cancelClosure: EmptyClosure
-  private let stringClosure: StringClosure
+  private let cancelClosure: () -> Void
+  private let stringClosure: (String) -> Void
   private var cancellables = Set<AnyCancellable>()
 
   public init(
-    _ cancelClosure: @escaping EmptyClosure,
-    _ stringClosure: @escaping StringClosure
+    _ cancelClosure: @escaping () -> Void,
+    _ stringClosure: @escaping (String) -> Void
   ) {
     self.stringClosure = stringClosure
     self.cancelClosure = cancelClosure
diff --git a/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
index ea56e1d63f504466c6104e66af735e8778a91aa1..1cfe3d251c7826bcad639009778dc9b26837f4a1 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSFTPController.swift
@@ -1,6 +1,5 @@
 import UIKit
 import Combine
-import DI
 import ScrollViewController
 
 public final class RestoreSFTPController: UIViewController {
diff --git a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
index c413c18a7cca79e3a144310f8923b669137d18e9..6fca825a4df49a270c800ca78b3f5d7757659a66 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
@@ -1,12 +1,13 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
-import DI
+import AppCore
+import Dependencies
+import AppNavigation
 
 public final class RestoreSuccessController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = RestoreSuccessView()
   private var cancellables = Set<AnyCancellable>()
@@ -17,7 +18,7 @@ public final class RestoreSuccessController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
index 0e30679443ab906f6ea0744e2360bc3c4a5f680a..40428ff3d9c49c175afb5d48d5cf8c18af28320b 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreListViewModel.swift
@@ -1,9 +1,10 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import CloudFiles
 import CloudFilesSFTP
-import DI
+import ComposableArchitecture
 
 public struct RestorationDetails {
   var provider: CloudService
@@ -11,7 +12,7 @@ public struct RestorationDetails {
 }
 
 final class RestoreListViewModel {
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
 
   var sftpPublisher: AnyPublisher<Void, Never> {
     sftpSubject.eraseToAnyPublisher()
@@ -51,33 +52,33 @@ final class RestoreListViewModel {
         case .success:
           onSuccess()
         case .failure(let error):
-          self.hudController.show(.init(error: error))
+          self.hudManager.show(.init(error: error))
         }
       }
     } catch {
-      hudController.show(.init(error: error))
+      hudManager.show(.init(error: error))
     }
   }
 
   func fetch(provider: CloudService) {
-    hudController.show()
+    hudManager.show()
     do {
       try CloudFilesManager.all[provider]!.fetch { [weak self] in
         guard let self else { return }
 
         switch $0 {
         case .success(let metadata):
-          self.hudController.dismiss()
+          self.hudManager.hide()
           self.detailsSubject.send(.init(
             provider: provider,
             metadata: metadata
           ))
         case .failure(let error):
-          self.hudController.show(.init(error: error))
+          self.hudManager.show(.init(error: error))
         }
       }
     } catch {
-      hudController.show(.init(error: error))
+      hudManager.show(.init(error: error))
     }
   }
 }
diff --git a/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
index 7b5eeaa3e703b8fac56874f576b100818da96124..d18036fc37123a30f56b7126b4e595e4e9a1a89b 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreSFTPViewModel.swift
@@ -4,7 +4,9 @@ import Combine
 import Foundation
 import CloudFiles
 import CloudFilesSFTP
-import DI
+
+import AppCore
+import ComposableArchitecture
 
 struct SFTPViewState {
   var host: String = ""
@@ -14,7 +16,7 @@ struct SFTPViewState {
 }
 
 final class RestoreSFTPViewModel {
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
 
   var statePublisher: AnyPublisher<SFTPViewState, Never> {
     stateSubject.eraseToAnyPublisher()
@@ -43,7 +45,7 @@ final class RestoreSFTPViewModel {
   }
 
   func didTapLogin() {
-    hudController.show()
+    hudManager.show()
 
     let host = stateSubject.value.host
     let username = stateSubject.value.username
@@ -62,14 +64,14 @@ final class RestoreSFTPViewModel {
         ).link(anyController) {
           switch $0 {
           case .success:
-            self.hudController.dismiss()
+            self.hudManager.hide()
             self.authSubject.send((host, username, password))
           case .failure(let error):
-            self.hudController.show(.init(error: error))
+            self.hudManager.show(.init(error: error))
           }
         }
       } catch {
-        self.hudController.show(.init(error: error))
+        self.hudManager.show(.init(error: error))
       }
     }
   }
diff --git a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
index 8555ff7de15b53fa96671df6cb2347a7608d06a1..8c0c4f2945ab51cc42ebead30c683f64efe67796 100644
--- a/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
+++ b/Sources/RestoreFeature/ViewModels/RestoreViewModel.swift
@@ -3,13 +3,15 @@ import Shared
 import Combine
 import Defaults
 import CloudFiles
-import DI
 
 import XXClient
 import XXModels
 import XXDatabase
 import XXMessengerClient
 
+import AppCore
+import ComposableArchitecture
+
 enum Step {
   case done
   case wrongPass
@@ -36,8 +38,8 @@ extension Step: Equatable {
 }
 
 final class RestoreViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
 
   @KeyObject(.phone, defaultValue: nil) var phone: String?
   @KeyObject(.email, defaultValue: nil) var email: String?
@@ -125,7 +127,7 @@ final class RestoreViewModel {
           onProgress: { print(">>> \($0)") }
         )
 
-        try self.database.saveContact(.init(
+        try self.dbManager.getDB().saveContact(.init(
           id: self.messenger.e2e.get()!.getContact().getId(),
           marshaled: self.messenger.e2e.get()!.getContact().data,
           username: self.username!,
@@ -146,7 +148,7 @@ final class RestoreViewModel {
         multilookup.contacts.forEach {
           print(">>> Found \(try! $0.getFact(.username)?.value)")
 
-          try! self.database.saveContact(.init(
+          try! self.dbManager.getDB().saveContact(.init(
             id: try $0.getId(),
             marshaled: $0.data,
             username: try? $0.getFact(.username)?.value,
diff --git a/Sources/RestoreFeature/Views/RestoreDetailsView.swift b/Sources/RestoreFeature/Views/RestoreDetailsView.swift
index 55f18c4d2befcd5dcfd9fa296fe7f6c888fd1aee..b7fad9fbd8c71b50306c9efd66fbcc51b3904e6a 100644
--- a/Sources/RestoreFeature/Views/RestoreDetailsView.swift
+++ b/Sources/RestoreFeature/Views/RestoreDetailsView.swift
@@ -1,56 +1,57 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RestoreDetailsView: UIView {
-    let separatorView = UIView()
-    let imageView = UIImageView()
-    let titleLabel = UILabel()
-
-    let stackView = UIStackView()
-    let dateView = DetailRowButton()
-    let sizeView = DetailRowButton()
-
-    init() {
-        super.init(frame: .zero)
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        titleLabel.textColor = Asset.neutralActive.color
-
-        stackView.axis = .vertical
-        stackView.spacing = 22
-        stackView.addArrangedSubview(dateView)
-        stackView.addArrangedSubview(sizeView)
-
-        addSubview(separatorView)
-        addSubview(imageView)
-        addSubview(titleLabel)
-        addSubview(stackView)
-
-        separatorView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(25)
-            make.right.equalToSuperview().offset(-25)
-            make.height.equalTo(1)
-        }
-
-        imageView.snp.makeConstraints { make in
-            make.top.equalTo(separatorView.snp.bottom).offset(40)
-            make.left.equalToSuperview().offset(24)
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.centerY.equalTo(imageView)
-            make.left.equalToSuperview().offset(92)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(20)
-            make.left.equalTo(titleLabel)
-            make.right.equalToSuperview().offset(-40)
-            make.bottom.lessThanOrEqualToSuperview().offset(-20)
-        }
+  let separatorView = UIView()
+  let imageView = UIImageView()
+  let titleLabel = UILabel()
+
+  let stackView = UIStackView()
+  let dateView = DetailRowButton()
+  let sizeView = DetailRowButton()
+
+  init() {
+    super.init(frame: .zero)
+    separatorView.backgroundColor = Asset.neutralLine.color
+
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    titleLabel.textColor = Asset.neutralActive.color
+
+    stackView.axis = .vertical
+    stackView.spacing = 22
+    stackView.addArrangedSubview(dateView)
+    stackView.addArrangedSubview(sizeView)
+
+    addSubview(separatorView)
+    addSubview(imageView)
+    addSubview(titleLabel)
+    addSubview(stackView)
+
+    separatorView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview().offset(25)
+      make.right.equalToSuperview().offset(-25)
+      make.height.equalTo(1)
     }
 
-    required init?(coder: NSCoder) { nil }
+    imageView.snp.makeConstraints { make in
+      make.top.equalTo(separatorView.snp.bottom).offset(40)
+      make.left.equalToSuperview().offset(24)
+    }
+
+    titleLabel.snp.makeConstraints { make in
+      make.centerY.equalTo(imageView)
+      make.left.equalToSuperview().offset(92)
+    }
+
+    stackView.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(20)
+      make.left.equalTo(titleLabel)
+      make.right.equalToSuperview().offset(-40)
+      make.bottom.lessThanOrEqualToSuperview().offset(-20)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RestoreFeature/Views/RestoreListView.swift b/Sources/RestoreFeature/Views/RestoreListView.swift
index a955173a742b7c0b94f95601f90634353ada327f..bb8f4e5a0767c2c6a81002e36b3ddb491ce4569f 100644
--- a/Sources/RestoreFeature/Views/RestoreListView.swift
+++ b/Sources/RestoreFeature/Views/RestoreListView.swift
@@ -1,127 +1,128 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RestoreListView: UIView {
-    let titleLabel = UILabel()
-    let stackView = UIStackView()
-    let firstSubtitleLabel = UILabel()
-    let secondSubtitleLabel = UILabel()
-    let sftpButton = RowButton()
-    let driveButton = RowButton()
-    let icloudButton = RowButton()
-    let dropboxButton = RowButton()
-    let cancelButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        setupTitle(Localized.AccountRestore.List.title)
-        setupSubtitle(Localized.AccountRestore.List.firstSubtitle)
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        let attrString = NSMutableAttributedString(
-            string: Localized.AccountRestore.List.secondSubtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ]
-        )
-
-        secondSubtitleLabel.numberOfLines = 0
-        secondSubtitleLabel.attributedText = attrString
-
-        sftpButton.setup(title: Localized.Backup.sftp, icon: Asset.restoreSFTP.image)
-        icloudButton.setup(title: Localized.Backup.iCloud, icon: Asset.restoreIcloud.image)
-        dropboxButton.setup(title: Localized.Backup.dropbox, icon: Asset.restoreDropbox.image)
-        driveButton.setup(title: Localized.Backup.googleDrive, icon: Asset.restoreDrive.image)
-
-        cancelButton.set(style: .seeThrough, title: Localized.AccountRestore.List.cancel)
-
-        stackView.axis = .vertical
-        stackView.distribution = .fillEqually
-        stackView.addArrangedSubview(driveButton)
-        stackView.addArrangedSubview(icloudButton)
-        stackView.addArrangedSubview(dropboxButton)
-        stackView.addArrangedSubview(sftpButton)
-
-        addSubview(titleLabel)
-        addSubview(firstSubtitleLabel)
-        addSubview(secondSubtitleLabel)
-        addSubview(stackView)
-        addSubview(cancelButton)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(safeAreaLayoutGuide).offset(15)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        firstSubtitleLabel.snp.makeConstraints {
-            $0.top.equalTo(titleLabel.snp.bottom).offset(8)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        secondSubtitleLabel.snp.makeConstraints {
-            $0.top.equalTo(firstSubtitleLabel.snp.bottom).offset(8)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(secondSubtitleLabel.snp.bottom).offset(28)
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-        }
-
-        cancelButton.snp.makeConstraints {
-            $0.top.greaterThanOrEqualTo(stackView.snp.bottom).offset(20)
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-            $0.bottom.equalTo(safeAreaLayoutGuide).offset(-50)
-        }
+  let titleLabel = UILabel()
+  let stackView = UIStackView()
+  let firstSubtitleLabel = UILabel()
+  let secondSubtitleLabel = UILabel()
+  let sftpButton = RowButton()
+  let driveButton = RowButton()
+  let icloudButton = RowButton()
+  let dropboxButton = RowButton()
+  let cancelButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    setupTitle(Localized.AccountRestore.List.title)
+    setupSubtitle(Localized.AccountRestore.List.firstSubtitle)
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+
+    let attrString = NSMutableAttributedString(
+      string: Localized.AccountRestore.List.secondSubtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ]
+    )
+
+    secondSubtitleLabel.numberOfLines = 0
+    secondSubtitleLabel.attributedText = attrString
+
+    sftpButton.setup(title: Localized.Backup.sftp, icon: Asset.restoreSFTP.image)
+    icloudButton.setup(title: Localized.Backup.iCloud, icon: Asset.restoreIcloud.image)
+    dropboxButton.setup(title: Localized.Backup.dropbox, icon: Asset.restoreDropbox.image)
+    driveButton.setup(title: Localized.Backup.googleDrive, icon: Asset.restoreDrive.image)
+
+    cancelButton.set(style: .seeThrough, title: Localized.AccountRestore.List.cancel)
+
+    stackView.axis = .vertical
+    stackView.distribution = .fillEqually
+    stackView.addArrangedSubview(driveButton)
+    stackView.addArrangedSubview(icloudButton)
+    stackView.addArrangedSubview(dropboxButton)
+    stackView.addArrangedSubview(sftpButton)
+
+    addSubview(titleLabel)
+    addSubview(firstSubtitleLabel)
+    addSubview(secondSubtitleLabel)
+    addSubview(stackView)
+    addSubview(cancelButton)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(15)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    private func setupTitle(_ title: String) {
-        let attString = NSMutableAttributedString(string: title)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 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)
+    firstSubtitleLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
 
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
+    secondSubtitleLabel.snp.makeConstraints {
+      $0.top.equalTo(firstSubtitleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
 
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(secondSubtitleLabel.snp.bottom).offset(28)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
     }
 
-    private func setupSubtitle(_ subtitle: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        let attString = NSAttributedString(
-            string: subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ])
-
-        firstSubtitleLabel.numberOfLines = 0
-        firstSubtitleLabel.attributedText = attString
+    cancelButton.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(stackView.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 }
+
+  private func setupTitle(_ title: String) {
+    let attString = NSMutableAttributedString(string: title)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 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
+
+    let attString = NSAttributedString(
+      string: subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ])
+
+    firstSubtitleLabel.numberOfLines = 0
+    firstSubtitleLabel.attributedText = attString
+  }
 }
diff --git a/Sources/RestoreFeature/Views/RestorePassphraseView.swift b/Sources/RestoreFeature/Views/RestorePassphraseView.swift
index 6dfaa4d716ae2a354ab9afa4a0d9563df97cc3f8..9eecc341c17383fd45c1a3eea48d810701e91222 100644
--- a/Sources/RestoreFeature/Views/RestorePassphraseView.swift
+++ b/Sources/RestoreFeature/Views/RestorePassphraseView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class RestorePassphraseView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/RestoreFeature/Views/RestoreProgressView.swift b/Sources/RestoreFeature/Views/RestoreProgressView.swift
index 95a471f02bf53bf936ca1cd30d98217bc3afde7c..bde3b25657b8ff55cbdc6288e37f1bed7c0e695e 100644
--- a/Sources/RestoreFeature/Views/RestoreProgressView.swift
+++ b/Sources/RestoreFeature/Views/RestoreProgressView.swift
@@ -1,87 +1,88 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RestoreProgressView: UIView {
-    let progressBarFull = UIView()
-    let progressBarFiller = UIView()
-    let progressLabel = UILabel()
-    let warningLabel = UILabel()
-    let descriptiveProgressLabel = UILabel()
-
-    init() {
-        super.init(frame: .zero)
-        warningLabel.textColor = Asset.neutralDisabled.color
-        progressLabel.textColor = Asset.neutralDisabled.color
-        descriptiveProgressLabel.textColor = Asset.neutralDisabled.color
-
-        warningLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        progressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        descriptiveProgressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        descriptiveProgressLabel.textAlignment = .center
-
-        progressBarFull.backgroundColor = Asset.neutralLine.color
-        progressBarFiller.backgroundColor = Asset.brandPrimary.color
-        progressBarFull.layer.masksToBounds = true
-        progressBarFull.layer.cornerRadius = 4
-
-        warningLabel.numberOfLines = 0
-        descriptiveProgressLabel.numberOfLines = 0
-        warningLabel.text = "This may take up to 5 mins, please don’t close the app and don’t put in background and don’t close your phone screen"
-
-        addSubview(progressBarFull)
-        addSubview(progressLabel)
-        addSubview(warningLabel)
-        addSubview(descriptiveProgressLabel)
-        progressBarFull.addSubview(progressBarFiller)
-
-        descriptiveProgressLabel.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualToSuperview()
-            make.left.equalToSuperview().offset(42)
-            make.right.equalToSuperview().offset(-42)
-            make.bottom.equalTo(progressBarFull.snp.top).offset(-15)
-        }
-
-        progressBarFull.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualToSuperview()
-            make.left.equalToSuperview().offset(42)
-            make.right.equalToSuperview().offset(-42)
-            make.centerY.equalToSuperview()
-            make.height.equalTo(8)
-        }
-
-        progressBarFiller.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.width.equalTo(0)
-            make.bottom.equalToSuperview()
-        }
-
-        progressLabel.snp.makeConstraints { make in
-            make.top.equalTo(progressBarFull.snp.bottom).offset(15)
-            make.left.equalToSuperview().offset(42)
-            make.right.equalToSuperview().offset(-42)
-        }
-
-        warningLabel.snp.makeConstraints { make in
-            make.top.equalTo(progressLabel.snp.bottom).offset(15)
-            make.left.equalToSuperview().offset(42)
-            make.right.equalToSuperview().offset(-42)
-            make.bottom.lessThanOrEqualToSuperview()
-        }
+  let progressBarFull = UIView()
+  let progressBarFiller = UIView()
+  let progressLabel = UILabel()
+  let warningLabel = UILabel()
+  let descriptiveProgressLabel = UILabel()
+
+  init() {
+    super.init(frame: .zero)
+    warningLabel.textColor = Asset.neutralDisabled.color
+    progressLabel.textColor = Asset.neutralDisabled.color
+    descriptiveProgressLabel.textColor = Asset.neutralDisabled.color
+
+    warningLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    progressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    descriptiveProgressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    descriptiveProgressLabel.textAlignment = .center
+
+    progressBarFull.backgroundColor = Asset.neutralLine.color
+    progressBarFiller.backgroundColor = Asset.brandPrimary.color
+    progressBarFull.layer.masksToBounds = true
+    progressBarFull.layer.cornerRadius = 4
+
+    warningLabel.numberOfLines = 0
+    descriptiveProgressLabel.numberOfLines = 0
+    warningLabel.text = "This may take up to 5 mins, please don’t close the app and don’t put in background and don’t close your phone screen"
+
+    addSubview(progressBarFull)
+    addSubview(progressLabel)
+    addSubview(warningLabel)
+    addSubview(descriptiveProgressLabel)
+    progressBarFull.addSubview(progressBarFiller)
+
+    descriptiveProgressLabel.snp.makeConstraints { make in
+      make.top.greaterThanOrEqualToSuperview()
+      make.left.equalToSuperview().offset(42)
+      make.right.equalToSuperview().offset(-42)
+      make.bottom.equalTo(progressBarFull.snp.top).offset(-15)
     }
 
-    required init?(coder: NSCoder) { nil }
+    progressBarFull.snp.makeConstraints { make in
+      make.top.greaterThanOrEqualToSuperview()
+      make.left.equalToSuperview().offset(42)
+      make.right.equalToSuperview().offset(-42)
+      make.centerY.equalToSuperview()
+      make.height.equalTo(8)
+    }
+
+    progressBarFiller.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.width.equalTo(0)
+      make.bottom.equalToSuperview()
+    }
+
+    progressLabel.snp.makeConstraints { make in
+      make.top.equalTo(progressBarFull.snp.bottom).offset(15)
+      make.left.equalToSuperview().offset(42)
+      make.right.equalToSuperview().offset(-42)
+    }
+
+    warningLabel.snp.makeConstraints { make in
+      make.top.equalTo(progressLabel.snp.bottom).offset(15)
+      make.left.equalToSuperview().offset(42)
+      make.right.equalToSuperview().offset(-42)
+      make.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
 
-    func update(downloaded: Float, total: Float) {
-        let totalkb = String(format: "%.1f kb", total/1000)
-        let downloadedKb = String(format: "%.1f kb", downloaded/1000)
-        let percent = String(format: "%.0f", downloaded/total * 100)
+  func update(downloaded: Float, total: Float) {
+    let totalkb = String(format: "%.1f kb", total/1000)
+    let downloadedKb = String(format: "%.1f kb", downloaded/1000)
+    let percent = String(format: "%.0f", downloaded/total * 100)
 
-        progressLabel.text = "Downloaded \(downloadedKb) of \(totalkb) (\(percent)%)"
+    progressLabel.text = "Downloaded \(downloadedKb) of \(totalkb) (\(percent)%)"
 
-        progressBarFiller.snp.updateConstraints { make in
-            make.width.equalTo(CGFloat(downloaded/total) * progressBarFull.frame.size.width)
-        }
+    progressBarFiller.snp.updateConstraints { make in
+      make.width.equalTo(CGFloat(downloaded/total) * progressBarFull.frame.size.width)
     }
+  }
 }
diff --git a/Sources/RestoreFeature/Views/RestoreSFTPView.swift b/Sources/RestoreFeature/Views/RestoreSFTPView.swift
index 5c12026bf8eda8865a226df8886c11a05108740a..e6595e9f9cd31fe6dcb85447049eb32f3dafdb76 100644
--- a/Sources/RestoreFeature/Views/RestoreSFTPView.swift
+++ b/Sources/RestoreFeature/Views/RestoreSFTPView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class RestoreSFTPView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/RestoreFeature/Views/RestoreSuccessView.swift b/Sources/RestoreFeature/Views/RestoreSuccessView.swift
index 35bdd4c04fc356e32b54a729b642514e504f8c38..ac6b3dea1ee72ec79ccc0d39202c6ab1c25bea1c 100644
--- a/Sources/RestoreFeature/Views/RestoreSuccessView.swift
+++ b/Sources/RestoreFeature/Views/RestoreSuccessView.swift
@@ -1,78 +1,79 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RestoreSuccessView: 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)
-        }
-
-        setTitle(Localized.AccountRestore.Success.title)
-        setSubtitle(Localized.AccountRestore.Success.subtitle)
+  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)
     }
 
-    required init?(coder: NSCoder) { nil }
+    titleLabel.snp.makeConstraints { make in
+      make.top.equalTo(iconImageView.snp.bottom).offset(40)
+      make.left.equalToSuperview().offset(40)
+      make.right.equalToSuperview().offset(-90)
+    }
 
-    private func setTitle(_ title: String) {
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.1
+    subtitleLabel.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(30)
+      make.left.equalToSuperview().offset(40)
+      make.right.equalToSuperview().offset(-90)
+    }
 
-        let attrString = NSMutableAttributedString(string: title)
+    nextButton.snp.makeConstraints { make in
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
+      make.bottom.equalToSuperview().offset(-60)
+    }
 
-        attrString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 39.0))
-        attrString.addAttribute(.foregroundColor, value: Asset.neutralWhite.color)
+    setTitle(Localized.AccountRestore.Success.title)
+    setSubtitle(Localized.AccountRestore.Success.subtitle)
+  }
 
-        attrString.addAttribute(
-            name: .foregroundColor,
-            value: Asset.neutralBody.color,
-            betweenCharacters: "#"
-        )
+  required init?(coder: NSCoder) { nil }
 
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attrString
-    }
+  private func setTitle(_ title: String) {
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.1
 
-    private func setSubtitle(_ subtitle: String?) {
-        subtitleLabel.text = subtitle
-    }
+    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
+  }
+
+  private func setSubtitle(_ subtitle: String?) {
+    subtitleLabel.text = subtitle
+  }
 }
diff --git a/Sources/RestoreFeature/Views/RestoreView.swift b/Sources/RestoreFeature/Views/RestoreView.swift
index 720128d33fa4bed8bd11e1ffed0873f9452682eb..d4bd3aeb238f38a894755497e1ff7a72bcc49c46 100644
--- a/Sources/RestoreFeature/Views/RestoreView.swift
+++ b/Sources/RestoreFeature/Views/RestoreView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import CloudFiles
+import AppResources
 
 final class RestoreView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/ScanFeature/Controllers/ScanContainerController.swift b/Sources/ScanFeature/Controllers/ScanContainerController.swift
index 68f78d7a6b6e0b64340ded20b05ae4f2dd06f197..435710b65d50319e33f4ab0bf1de67f538692f36 100644
--- a/Sources/ScanFeature/Controllers/ScanContainerController.swift
+++ b/Sources/ScanFeature/Controllers/ScanContainerController.swift
@@ -1,13 +1,15 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
 
 public final class ScanContainerController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = ScanContainerView()
 
@@ -40,7 +42,7 @@ public final class ScanContainerController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.lightContent)
+    statusBar.set(.lightContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
diff --git a/Sources/ScanFeature/Controllers/ScanController.swift b/Sources/ScanFeature/Controllers/ScanController.swift
index bf8875099a7ba127269d1b03e693015542c093bf..e21b9d035bf0d664a06d7f2873244747614f2bf9 100644
--- a/Sources/ScanFeature/Controllers/ScanController.swift
+++ b/Sources/ScanFeature/Controllers/ScanController.swift
@@ -1,19 +1,19 @@
 import UIKit
 import Shared
 import Combine
-import Permissions
-import Navigation
+import AppCore
+import AppNavigation
 import CombineSchedulers
-import DI
+import PermissionsFeature
+import ComposableArchitecture
 
 final class ScanController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var permissions: PermissionHandling
-  
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.permissions) var permissions: PermissionsManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
   private lazy var screenView = ScanView()
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-  
+
   private var status: ScanStatus?
   private let camera: CameraType
   private let viewModel = ScanViewModel()
@@ -54,18 +54,18 @@ final class ScanController: UIViewController {
   
   override func viewWillDisappear(_ animated: Bool) {
     super.viewWillDisappear(animated)
-    backgroundScheduler.schedule { [weak self] in
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       self.camera.stop()
     }
   }
   
   private func startCamera() {
-    permissions.requestCamera { [weak self] granted in
+    permissions.camera.request { [weak self] granted in
       guard let self else { return }
       
       if granted {
-        self.backgroundScheduler.schedule {
+        self.bgQueue.schedule {
           self.camera.start()
         }
       } else {
diff --git a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
index 5c20f1e3f9111ed699790503ffce76774f02cfe4..75410119075162b70a45a95e8622b36083bb637e 100644
--- a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
@@ -3,7 +3,8 @@ import Shared
 import Combine
 import Defaults
 import XXClient
-import DI
+import AppCore
+import Dependencies
 import XXMessengerClient
 
 struct ScanDisplayViewState: Equatable {
@@ -15,7 +16,7 @@ struct ScanDisplayViewState: Equatable {
 }
 
 final class ScanDisplayViewModel {
-    @Dependency var messenger: Messenger
+    @Dependency(\.app.messenger) var messenger: Messenger
 
     @KeyObject(.email, defaultValue: nil) var email: String?
     @KeyObject(.phone, defaultValue: nil) var phone: String?
diff --git a/Sources/ScanFeature/ViewModels/ScanViewModel.swift b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
index 1e4a79a99a43c192211aaf4a77d14ce889d6c9e2..d69cbd692028a4485b276e75e7209d85301b087b 100644
--- a/Sources/ScanFeature/ViewModels/ScanViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanViewModel.swift
@@ -1,96 +1,98 @@
 import Shared
+import AppCore
 import Combine
 import XXModels
 import XXClient
 import Foundation
+import AppResources
+import Dependencies
 import ReportingFeature
-import DI
 
 enum ScanStatus: Equatable {
-    case reading
-    case processing
-    case success
-    case failed(ScanError)
+  case reading
+  case processing
+  case success
+  case failed(ScanError)
 }
 
 enum ScanError: Equatable {
-    case requestOpened
-    case unknown(String)
-    case cameraPermission
-    case alreadyFriends(String)
+  case requestOpened
+  case unknown(String)
+  case cameraPermission
+  case alreadyFriends(String)
 }
 
 final class ScanViewModel {
-    @Dependency var database: Database
-    @Dependency var reportingStatus: ReportingStatus
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
 
-    var contactPublisher: AnyPublisher<XXModels.Contact, Never> {
-        contactSubject.eraseToAnyPublisher()
-    }
+  var contactPublisher: AnyPublisher<XXModels.Contact, Never> {
+    contactSubject.eraseToAnyPublisher()
+  }
 
-    var statePublisher: AnyPublisher<ScanStatus, Never> {
-        stateSubject.eraseToAnyPublisher()
-    }
+  var statePublisher: AnyPublisher<ScanStatus, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let contactSubject = PassthroughSubject<XXModels.Contact, Never>()
+  private let stateSubject = CurrentValueSubject<ScanStatus, Never>(.reading)
 
-    private let contactSubject = PassthroughSubject<XXModels.Contact, Never>()
-    private let stateSubject = CurrentValueSubject<ScanStatus, Never>(.reading)
+  func resetScanner() {
+    stateSubject.send(.reading)
+  }
 
-    func resetScanner() {
-        stateSubject.send(.reading)
+  func didScanData(_ data: Data) {
+    guard stateSubject.value == .reading else { return }
+    stateSubject.send(.processing)
+
+    let user = XXClient.Contact.live(data)
+
+    guard let uid = try? user.getId(),
+          let facts = try? user.getFacts(),
+          let username = facts.first(where: { $0.type == .username })?.value else {
+      let errorTitle = Localized.Scan.Error.invalid
+      stateSubject.send(.failed(.unknown(errorTitle)))
+      return
     }
 
-    func didScanData(_ data: Data) {
-        guard stateSubject.value == .reading else { return }
-        stateSubject.send(.processing)
-
-        let user = XXClient.Contact.live(data)
-
-        guard let uid = try? user.getId(),
-              let facts = try? user.getFacts(),
-              let username = facts.first(where: { $0.type == .username })?.value else {
-            let errorTitle = Localized.Scan.Error.invalid
-            stateSubject.send(.failed(.unknown(errorTitle)))
-            return
-        }
-
-        let email = facts.first { $0.type == .email }?.value
-        let phone = facts.first { $0.type == .phone }?.value
-
-        if let alreadyContact = try? database.fetchContacts(.init(id: [uid])).first {
-            if alreadyContact.isBlocked, reportingStatus.isEnabled() {
-                stateSubject.send(.failed(.unknown("You previously blocked this user.")))
-                return
-            }
-
-            if alreadyContact.isBanned, reportingStatus.isEnabled() {
-                stateSubject.send(.failed(.unknown("This user was banned.")))
-                return
-            }
-
-            if alreadyContact.authStatus == .friend {
-                stateSubject.send(.failed(.alreadyFriends(username)))
-            } else if [.requested, .verified].contains(alreadyContact.authStatus) {
-                stateSubject.send(.failed(.requestOpened))
-            } else {
-                let generalErrorTitle = Localized.Scan.Error.general
-                stateSubject.send(.failed(.unknown(generalErrorTitle)))
-            }
-
-            return
-        }
-
-        stateSubject.send(.success)
-        contactSubject.send(.init(
-            id: uid,
-            marshaled: data,
-            username: username,
-            email: email,
-            phone: phone,
-            nickname: nil,
-            photo: nil,
-            authStatus: .stranger,
-            isRecent: false,
-            createdAt: Date()
-        ))
+    let email = facts.first { $0.type == .email }?.value
+    let phone = facts.first { $0.type == .phone }?.value
+
+    if let alreadyContact = try? dbManager.getDB().fetchContacts(.init(id: [uid])).first {
+      if alreadyContact.isBlocked, reportingStatus.isEnabled() {
+        stateSubject.send(.failed(.unknown("You previously blocked this user.")))
+        return
+      }
+
+      if alreadyContact.isBanned, reportingStatus.isEnabled() {
+        stateSubject.send(.failed(.unknown("This user was banned.")))
+        return
+      }
+
+      if alreadyContact.authStatus == .friend {
+        stateSubject.send(.failed(.alreadyFriends(username)))
+      } else if [.requested, .verified].contains(alreadyContact.authStatus) {
+        stateSubject.send(.failed(.requestOpened))
+      } else {
+        let generalErrorTitle = Localized.Scan.Error.general
+        stateSubject.send(.failed(.unknown(generalErrorTitle)))
+      }
+
+      return
     }
+
+    stateSubject.send(.success)
+    contactSubject.send(.init(
+      id: uid,
+      marshaled: data,
+      username: username,
+      email: email,
+      phone: phone,
+      nickname: nil,
+      photo: nil,
+      authStatus: .stranger,
+      isRecent: false,
+      createdAt: Date()
+    ))
+  }
 }
diff --git a/Sources/ScanFeature/Views/AttributeSwitcher.swift b/Sources/ScanFeature/Views/AttributeSwitcher.swift
index 4bc957c6816dfc1c36b50ed5c47e46d6cf0180f5..464979a68754855cdd8b1c1f225acd2d66c4cb7e 100644
--- a/Sources/ScanFeature/Views/AttributeSwitcher.swift
+++ b/Sources/ScanFeature/Views/AttributeSwitcher.swift
@@ -1,102 +1,103 @@
 import UIKit
 import Shared
+import AppResources
 
 final class AttributeSwitcher: UIView {
-    struct State {
-        var content: String
-        var isVisible: Bool
+  struct State {
+    var content: String
+    var isVisible: Bool
+  }
+
+  private let titleLabel = UILabel()
+  private let contentLabel = UILabel()
+  private let stackView = UIStackView()
+  private(set) var switcherView = UISwitch()
+  private let verticalStackView = UIStackView()
+
+  private(set) var addButton: UIControl = {
+    let label = UILabel()
+    let icon = UIImageView()
+    let control = UIControl()
+
+    icon.image = Asset.scanAdd.image
+    label.text = Localized.Scan.Display.Share.add
+    label.textColor = Asset.brandPrimary.color
+
+    control.addSubview(icon)
+    control.addSubview(label)
+
+    icon.snp.makeConstraints {
+      $0.left.equalToSuperview()
+      $0.top.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.width.equalTo(icon.snp.height)
     }
 
-    private let titleLabel = UILabel()
-    private let contentLabel = UILabel()
-    private let stackView = UIStackView()
-    private(set) var switcherView = UISwitch()
-    private let verticalStackView = UIStackView()
-
-    private(set) var addButton: UIControl = {
-        let label = UILabel()
-        let icon = UIImageView()
-        let control = UIControl()
-
-        icon.image = Asset.scanAdd.image
-        label.text = Localized.Scan.Display.Share.add
-        label.textColor = Asset.brandPrimary.color
-
-        control.addSubview(icon)
-        control.addSubview(label)
-
-        icon.snp.makeConstraints {
-            $0.left.equalToSuperview()
-            $0.top.equalToSuperview()
-            $0.bottom.equalToSuperview()
-            $0.width.equalTo(icon.snp.height)
-        }
-
-        label.snp.makeConstraints {
-            $0.left.equalTo(icon.snp.right).offset(5)
-            $0.top.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    label.snp.makeConstraints {
+      $0.left.equalTo(icon.snp.right).offset(5)
+      $0.top.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
 
-        return control
-    }()
+    return control
+  }()
 
-    public init() {
-        super.init(frame: .zero)
+  public init() {
+    super.init(frame: .zero)
 
-        contentLabel.textColor = Asset.neutralActive.color
-        titleLabel.textColor = Asset.neutralWeak.color
-        switcherView.onTintColor = Asset.brandPrimary.color
+    contentLabel.textColor = Asset.neutralActive.color
+    titleLabel.textColor = Asset.neutralWeak.color
+    switcherView.onTintColor = Asset.brandPrimary.color
 
-        contentLabel.numberOfLines = 0
-        contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-        titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    contentLabel.numberOfLines = 0
+    contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
 
-        addSubview(stackView)
+    addSubview(stackView)
 
-        verticalStackView.spacing = 5
-        verticalStackView.axis = .vertical
-        verticalStackView.addArrangedSubview(titleLabel)
-        verticalStackView.addArrangedSubview(contentLabel)
+    verticalStackView.spacing = 5
+    verticalStackView.axis = .vertical
+    verticalStackView.addArrangedSubview(titleLabel)
+    verticalStackView.addArrangedSubview(contentLabel)
 
-        switcherView.setContentCompressionResistancePriority(.required, for: .vertical)
-        switcherView.setContentCompressionResistancePriority(.required, for: .horizontal)
+    switcherView.setContentCompressionResistancePriority(.required, for: .vertical)
+    switcherView.setContentCompressionResistancePriority(.required, for: .horizontal)
 
-        stackView.addArrangedSubview(verticalStackView)
-        stackView.addArrangedSubview(FlexibleSpace())
+    stackView.addArrangedSubview(verticalStackView)
+    stackView.addArrangedSubview(FlexibleSpace())
 
-        let otherHStack = UIStackView()
-        otherHStack.addArrangedSubview(addButton)
-        otherHStack.addArrangedSubview(switcherView)
+    let otherHStack = UIStackView()
+    otherHStack.addArrangedSubview(addButton)
+    otherHStack.addArrangedSubview(switcherView)
 
-        let otherVStack = UIStackView()
-        otherVStack.axis = .vertical
-        otherVStack.addArrangedSubview(otherHStack)
-        otherVStack.addArrangedSubview(FlexibleSpace())
+    let otherVStack = UIStackView()
+    otherVStack.axis = .vertical
+    otherVStack.addArrangedSubview(otherHStack)
+    otherVStack.addArrangedSubview(FlexibleSpace())
 
-        stackView.addArrangedSubview(otherVStack)
+    stackView.addArrangedSubview(otherVStack)
 
-        stackView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+    stackView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func setup(state: State?, title: String) {
-        titleLabel.text = title
+  func setup(state: State?, title: String) {
+    titleLabel.text = title
 
-        guard let state = state else {
-            addButton.isHidden = false
-            switcherView.isHidden = true
-            contentLabel.text = Localized.Scan.Display.Share.notAdded
-            return
-        }
-
-        addButton.isHidden = true
-        switcherView.isHidden = false
-        switcherView.isOn = state.isVisible
-        contentLabel.text = state.isVisible ? state.content : Localized.Scan.Display.Share.hidden
+    guard let state = state else {
+      addButton.isHidden = false
+      switcherView.isHidden = true
+      contentLabel.text = Localized.Scan.Display.Share.notAdded
+      return
     }
+
+    addButton.isHidden = true
+    switcherView.isHidden = false
+    switcherView.isOn = state.isVisible
+    contentLabel.text = state.isVisible ? state.content : Localized.Scan.Display.Share.hidden
+  }
 }
diff --git a/Sources/ScanFeature/Views/ScanContainerView.swift b/Sources/ScanFeature/Views/ScanContainerView.swift
index 5b9717598d93484ce74eb58e37b1ed465afc9230..78432064b4d1b02a22629b81e462e4239a14b322 100644
--- a/Sources/ScanFeature/Views/ScanContainerView.swift
+++ b/Sources/ScanFeature/Views/ScanContainerView.swift
@@ -1,36 +1,37 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ScanContainerView: UIView {
-    let stackView = UIStackView()
-    let leftButton = ScanSegmentedControlButton()
-    let rightButton = ScanSegmentedControlButton()
-
-    init() {
-        super.init(frame: .zero)
-
-        backgroundColor = Asset.neutralDark.color
-
-        leftButton.set(selected: true)
-        rightButton.set(selected: false)
-        leftButton.imageView.image = Asset.scanScan.image
-        rightButton.imageView.image = Asset.scanQr.image
-        leftButton.titleLabel.text = Localized.Scan.SegmentedControl.left
-        rightButton.titleLabel.text = Localized.Scan.SegmentedControl.right
-
-        stackView.distribution = .fillEqually
-        stackView.addArrangedSubview(leftButton)
-        stackView.addArrangedSubview(rightButton)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(safeAreaLayoutGuide).offset(10)
-            $0.left.equalToSuperview().offset(50)
-            $0.right.equalToSuperview().offset(-50)
-            $0.height.equalTo(60)
-        }
+  let stackView = UIStackView()
+  let leftButton = ScanSegmentedControlButton()
+  let rightButton = ScanSegmentedControlButton()
+
+  init() {
+    super.init(frame: .zero)
+
+    backgroundColor = Asset.neutralDark.color
+
+    leftButton.set(selected: true)
+    rightButton.set(selected: false)
+    leftButton.imageView.image = Asset.scanScan.image
+    rightButton.imageView.image = Asset.scanQr.image
+    leftButton.titleLabel.text = Localized.Scan.SegmentedControl.left
+    rightButton.titleLabel.text = Localized.Scan.SegmentedControl.right
+
+    stackView.distribution = .fillEqually
+    stackView.addArrangedSubview(leftButton)
+    stackView.addArrangedSubview(rightButton)
+
+    addSubview(stackView)
+
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(10)
+      $0.left.equalToSuperview().offset(50)
+      $0.right.equalToSuperview().offset(-50)
+      $0.height.equalTo(60)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ScanFeature/Views/ScanDisplayShareView.swift b/Sources/ScanFeature/Views/ScanDisplayShareView.swift
index acad98f7cab2ffd36c0b210737c17cd26dc21904..87beade8fdb98b3d6e07040d71ea072f27588234 100644
--- a/Sources/ScanFeature/Views/ScanDisplayShareView.swift
+++ b/Sources/ScanFeature/Views/ScanDisplayShareView.swift
@@ -2,197 +2,198 @@ import UIKit
 import Shared
 import SnapKit
 import Combine
+import AppResources
 
 final class ScanDisplayShareView: UIView {
-    enum Action {
-        case info
-        case addEmail
-        case addPhone
-        case toggleEmail
-        case togglePhone
+  enum Action {
+    case info
+    case addEmail
+    case addPhone
+    case toggleEmail
+    case togglePhone
+  }
+  
+  private var isExpanded = false {
+    didSet { updateBottomConstraint() }
+  }
+  
+  private let upperView = UIView()
+  private let lowerView = UIView()
+  private var bottomConstraint: Constraint?
+  
+  private let imageView = UIImageView()
+  private let titleView = TextWithInfoView()
+  private let emailView = AttributeSwitcher()
+  private let phoneView = AttributeSwitcher()
+  private var cancellables = Set<AnyCancellable>()
+  
+  private var currentConstraintConstant: CGFloat = 0.0 {
+    didSet { bottomConstraint?.update(offset: currentConstraintConstant) }
+  }
+  
+  private var bottomConstraintExpanded: CGFloat {
+    -lowerView.frame.height
+  }
+  
+  private var bottomConstraintNotExpanded: CGFloat {
+    0
+  }
+  
+  var actionPublisher: AnyPublisher<Action, Never> {
+    actionSubject.eraseToAnyPublisher()
+  }
+  
+  private let actionSubject = PassthroughSubject<Action, Never>()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    upperView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))
+    lowerView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))
+    
+    layer.cornerRadius = 30
+    imageView.image = Asset.scanDropdown.image
+    backgroundColor = Asset.neutralWhite.color
+    clipsToBounds = true
+    layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
+    
+    addSubview(upperView)
+    addSubview(lowerView)
+    
+    upperView.addSubview(imageView)
+    upperView.addSubview(titleView)
+    lowerView.addSubview(emailView)
+    lowerView.addSubview(phoneView)
+    
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.lineBreakMode = .byWordWrapping
+    
+    titleView.setup(
+      text: Localized.Scan.Display.Share.title,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraphStyle
+      ],
+      didTapInfo: { [weak self] in self?.actionSubject.send(.info) }
+    )
+    
+    emailView.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in actionSubject.send(.toggleEmail) }
+      .store(in: &cancellables)
+    
+    phoneView.switcherView
+      .publisher(for: .valueChanged)
+      .sink { [unowned self] in actionSubject.send(.togglePhone) }
+      .store(in: &cancellables)
+    
+    emailView.addButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in actionSubject.send(.addEmail) }
+      .store(in: &cancellables)
+    
+    phoneView.addButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in actionSubject.send(.addPhone) }
+      .store(in: &cancellables)
+    
+    emailView.setup(state: nil, title: Localized.Scan.Display.Share.email)
+    phoneView.setup(state: nil, title: Localized.Scan.Display.Share.phone)
+    emailView.alpha = 0.0
+    phoneView.alpha = 0.0
+    
+    imageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.centerX.equalToSuperview()
     }
-
-    private var isExpanded = false {
-        didSet { updateBottomConstraint() }
-    }
-
-    private let upperView = UIView()
-    private let lowerView = UIView()
-    private var bottomConstraint: Constraint?
-
-    private let imageView = UIImageView()
-    private let titleView = TextWithInfoView()
-    private let emailView = AttributeSwitcher()
-    private let phoneView = AttributeSwitcher()
-    private var cancellables = Set<AnyCancellable>()
-
-    private var currentConstraintConstant: CGFloat = 0.0 {
-        didSet { bottomConstraint?.update(offset: currentConstraintConstant) }
+    
+    titleView.snp.makeConstraints {
+      $0.top.equalTo(imageView.snp.bottom).offset(10)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.lessThanOrEqualToSuperview().offset(-40)
+      $0.centerY.equalToSuperview()
     }
-
-    private var bottomConstraintExpanded: CGFloat {
-        -lowerView.frame.height
-    }
-
-    private var bottomConstraintNotExpanded: CGFloat {
-        0
-    }
-
-    var actionPublisher: AnyPublisher<Action, Never> {
-        actionSubject.eraseToAnyPublisher()
+    
+    emailView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
     }
-
-    private let actionSubject = PassthroughSubject<Action, Never>()
-
-    init() {
-        super.init(frame: .zero)
-
-        upperView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))
-        lowerView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(didPan(_:))))
-
-        layer.cornerRadius = 30
-        imageView.image = Asset.scanDropdown.image
-        backgroundColor = Asset.neutralWhite.color
-        clipsToBounds = true
-        layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
-
-        addSubview(upperView)
-        addSubview(lowerView)
-
-        upperView.addSubview(imageView)
-        upperView.addSubview(titleView)
-        lowerView.addSubview(emailView)
-        lowerView.addSubview(phoneView)
-
-        let paragraphStyle = NSMutableParagraphStyle()
-        paragraphStyle.lineBreakMode = .byWordWrapping
-
-        titleView.setup(
-            text: Localized.Scan.Display.Share.title,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraphStyle
-            ],
-            didTapInfo: { [weak self] in self?.actionSubject.send(.info) }
-        )
-
-        emailView.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in actionSubject.send(.toggleEmail) }
-            .store(in: &cancellables)
-
-        phoneView.switcherView
-            .publisher(for: .valueChanged)
-            .sink { [unowned self] in actionSubject.send(.togglePhone) }
-            .store(in: &cancellables)
-
-        emailView.addButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in actionSubject.send(.addEmail) }
-            .store(in: &cancellables)
-
-        phoneView.addButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in actionSubject.send(.addPhone) }
-            .store(in: &cancellables)
-
-        emailView.setup(state: nil, title: Localized.Scan.Display.Share.email)
-        phoneView.setup(state: nil, title: Localized.Scan.Display.Share.phone)
-        emailView.alpha = 0.0
-        phoneView.alpha = 0.0
-
-        imageView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.centerX.equalToSuperview()
-        }
-
-        titleView.snp.makeConstraints {
-            $0.top.equalTo(imageView.snp.bottom).offset(10)
-            $0.left.equalToSuperview().offset(40)
-            $0.right.lessThanOrEqualToSuperview().offset(-40)
-            $0.centerY.equalToSuperview()
-        }
-
-        emailView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-        }
-
-        phoneView.snp.makeConstraints {
-            $0.top.equalTo(emailView.snp.bottom).offset(25)
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-            $0.bottom.equalToSuperview().offset(-40)
-        }
-
-        upperView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            bottomConstraint = $0.bottom
-                .equalTo(safeAreaLayoutGuide)
-                .constraint
-        }
-
-        lowerView.snp.makeConstraints {
-            $0.top.equalTo(upperView.snp.bottom).offset(-30)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-        }
+    
+    phoneView.snp.makeConstraints {
+      $0.top.equalTo(emailView.snp.bottom).offset(25)
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalToSuperview().offset(-40)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setup(email state: AttributeSwitcher.State?) {
-        emailView.setup(state: state, title: Localized.Scan.Display.Share.email)
+    
+    upperView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      bottomConstraint = $0.bottom
+        .equalTo(safeAreaLayoutGuide)
+        .constraint
     }
-
-    func setup(phone state: AttributeSwitcher.State?) {
-        phoneView.setup(state: state, title: Localized.Scan.Display.Share.phone)
+    
+    lowerView.snp.makeConstraints {
+      $0.top.equalTo(upperView.snp.bottom).offset(-30)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
     }
-
-    @objc private func didPan(_ sender: UIPanGestureRecognizer) {
-        switch sender.state {
-        case .began, .changed:
-            let isUpwards = sender.translation(in: self).y < 0
-            let result = currentConstraintConstant + sender.translation(in: self).y
-
-            if isUpwards {
-                currentConstraintConstant = max(bottomConstraintExpanded, result)
-            } else {
-                currentConstraintConstant = min(bottomConstraintNotExpanded, result)
-            }
-
-            let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
-            let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
-            let alpha = 1 - (currentMinusExpanded / abs(notExpandedMinusExpanded))
-            emailView.alpha = alpha
-            phoneView.alpha = alpha
-
-        case .cancelled, .ended, .failed:
-            let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
-            let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
-            let percentage = currentMinusExpanded / abs(notExpandedMinusExpanded)
-            isExpanded = percentage < 0.5
-
-        case .possible:
-            break
-        @unknown default:
-            break
-        }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  func setup(email state: AttributeSwitcher.State?) {
+    emailView.setup(state: state, title: Localized.Scan.Display.Share.email)
+  }
+  
+  func setup(phone state: AttributeSwitcher.State?) {
+    phoneView.setup(state: state, title: Localized.Scan.Display.Share.phone)
+  }
+  
+  @objc private func didPan(_ sender: UIPanGestureRecognizer) {
+    switch sender.state {
+    case .began, .changed:
+      let isUpwards = sender.translation(in: self).y < 0
+      let result = currentConstraintConstant + sender.translation(in: self).y
+      
+      if isUpwards {
+        currentConstraintConstant = max(bottomConstraintExpanded, result)
+      } else {
+        currentConstraintConstant = min(bottomConstraintNotExpanded, result)
+      }
+      
+      let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
+      let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
+      let alpha = 1 - (currentMinusExpanded / abs(notExpandedMinusExpanded))
+      emailView.alpha = alpha
+      phoneView.alpha = alpha
+      
+    case .cancelled, .ended, .failed:
+      let currentMinusExpanded = currentConstraintConstant - bottomConstraintExpanded
+      let notExpandedMinusExpanded = bottomConstraintNotExpanded - bottomConstraintExpanded
+      let percentage = currentMinusExpanded / abs(notExpandedMinusExpanded)
+      isExpanded = percentage < 0.5
+      
+    case .possible:
+      break
+    @unknown default:
+      break
     }
-
-    private func updateBottomConstraint() {
-        if isExpanded {
-            emailView.alpha = 1.0
-            phoneView.alpha = 1.0
-            currentConstraintConstant = bottomConstraintExpanded
-        } else {
-            emailView.alpha = 0.0
-            phoneView.alpha = 0.0
-            currentConstraintConstant = bottomConstraintNotExpanded
-        }
+  }
+  
+  private func updateBottomConstraint() {
+    if isExpanded {
+      emailView.alpha = 1.0
+      phoneView.alpha = 1.0
+      currentConstraintConstant = bottomConstraintExpanded
+    } else {
+      emailView.alpha = 0.0
+      phoneView.alpha = 0.0
+      currentConstraintConstant = bottomConstraintNotExpanded
     }
+  }
 }
diff --git a/Sources/ScanFeature/Views/ScanDisplayView.swift b/Sources/ScanFeature/Views/ScanDisplayView.swift
index fa2b02438c0d735708b9a30ffc4a6c2228926890..5c3bf28c2f7ce73826007a228cd8f9c00e7027ad 100644
--- a/Sources/ScanFeature/Views/ScanDisplayView.swift
+++ b/Sources/ScanFeature/Views/ScanDisplayView.swift
@@ -1,101 +1,102 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class ScanDisplayView: UIView {
-    var actionPublisher: AnyPublisher<ScanDisplayShareView.Action, Never> {
-        shareSheetView.actionPublisher.eraseToAnyPublisher()
+  var actionPublisher: AnyPublisher<ScanDisplayShareView.Action, Never> {
+    shareSheetView.actionPublisher.eraseToAnyPublisher()
+  }
+
+  private let copyLabel = UILabel()
+  private let codeButton = ScanQRButton()
+  private let copyImageView = UIImageView()
+  private let copyContainerButton = UIControl()
+  private var cancellables = Set<AnyCancellable>()
+  private let shareSheetView = ScanDisplayShareView()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralDark.color
+
+    copyImageView.image = Asset.scanCopy.image
+    copyLabel.text = Localized.Scan.Display.copy
+    copyLabel.textColor = Asset.neutralDisabled.color
+    copyLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+
+    codeButton.publisher(for: .touchUpInside)
+      .merge(with: copyContainerButton.publisher(for: .touchUpInside))
+      .sink { [unowned self] in
+        UIGraphicsBeginImageContext(codeButton.frame.size)
+        codeButton.layer.render(in: UIGraphicsGetCurrentContext()!)
+        let output = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+
+        UIImageWriteToSavedPhotosAlbum(output!, nil, nil, nil)
+        codeButton.blinkCopied()
+      }.store(in: &cancellables)
+
+    addSubview(codeButton)
+    addSubview(copyContainerButton)
+    copyContainerButton.addSubview(copyLabel)
+    copyContainerButton.addSubview(copyImageView)
+
+    addSubview(shareSheetView)
+
+    codeButton.snp.makeConstraints {
+      $0.centerX.equalTo(safeAreaLayoutGuide)
+      $0.centerY.equalTo(safeAreaLayoutGuide).multipliedBy(0.6)
+      $0.width.equalTo(safeAreaLayoutGuide).multipliedBy(0.6)
+      $0.height.equalTo(codeButton.snp.width)
     }
 
-    private let copyLabel = UILabel()
-    private let codeButton = ScanQRButton()
-    private let copyImageView = UIImageView()
-    private let copyContainerButton = UIControl()
-    private var cancellables = Set<AnyCancellable>()
-    private let shareSheetView = ScanDisplayShareView()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralDark.color
-
-        copyImageView.image = Asset.scanCopy.image
-        copyLabel.text = Localized.Scan.Display.copy
-        copyLabel.textColor = Asset.neutralDisabled.color
-        copyLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-
-        codeButton.publisher(for: .touchUpInside)
-            .merge(with: copyContainerButton.publisher(for: .touchUpInside))
-            .sink { [unowned self] in
-                UIGraphicsBeginImageContext(codeButton.frame.size)
-                codeButton.layer.render(in: UIGraphicsGetCurrentContext()!)
-                let output = UIGraphicsGetImageFromCurrentImageContext()
-                UIGraphicsEndImageContext()
-
-                UIImageWriteToSavedPhotosAlbum(output!, nil, nil, nil)
-                codeButton.blinkCopied()
-            }.store(in: &cancellables)
-
-        addSubview(codeButton)
-        addSubview(copyContainerButton)
-        copyContainerButton.addSubview(copyLabel)
-        copyContainerButton.addSubview(copyImageView)
-
-        addSubview(shareSheetView)
-
-        codeButton.snp.makeConstraints {
-            $0.centerX.equalTo(safeAreaLayoutGuide)
-            $0.centerY.equalTo(safeAreaLayoutGuide).multipliedBy(0.6)
-            $0.width.equalTo(safeAreaLayoutGuide).multipliedBy(0.6)
-            $0.height.equalTo(codeButton.snp.width)
-        }
-
-        copyContainerButton.snp.makeConstraints {
-            $0.top.equalTo(codeButton.snp.bottom).offset(33)
-            $0.centerX.equalTo(codeButton)
-        }
-
-        copyImageView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        copyLabel.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalTo(copyImageView.snp.right).offset(5)
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        shareSheetView.snp.makeConstraints {
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    copyContainerButton.snp.makeConstraints {
+      $0.top.equalTo(codeButton.snp.bottom).offset(33)
+      $0.centerX.equalTo(codeButton)
     }
 
-    required init?(coder: NSCoder) { nil }
+    copyImageView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+
+    copyLabel.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalTo(copyImageView.snp.right).offset(5)
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
 
-    func setup(code image: CIImage) {
-        codeButton.setup(code: image)
+    shareSheetView.snp.makeConstraints {
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setup(code image: CIImage) {
+    codeButton.setup(code: image)
+  }
+
+  func setupAttributes(
+    email: String?,
+    phone: String?,
+    emailSharing: Bool,
+    phoneSharing: Bool
+  ) {
+    if let email = email {
+      shareSheetView.setup(email: .init(content: email, isVisible: emailSharing))
+    } else {
+      shareSheetView.setup(email: nil)
     }
 
-    func setupAttributes(
-        email: String?,
-        phone: String?,
-        emailSharing: Bool,
-        phoneSharing: Bool
-    ) {
-        if let email = email {
-            shareSheetView.setup(email: .init(content: email, isVisible: emailSharing))
-        } else {
-            shareSheetView.setup(email: nil)
-        }
-
-        if let phone = phone {
-            shareSheetView.setup(phone: .init(content: phone, isVisible: phoneSharing))
-        } else {
-            shareSheetView.setup(phone: nil)
-        }
+    if let phone = phone {
+      shareSheetView.setup(phone: .init(content: phone, isVisible: phoneSharing))
+    } else {
+      shareSheetView.setup(phone: nil)
     }
+  }
 }
diff --git a/Sources/ScanFeature/Views/ScanOverlayView.swift b/Sources/ScanFeature/Views/ScanOverlayView.swift
index 14bc4c5dc736a388a41d9c04f21a51fa49467e99..060bfbdac4476f7c2a020ee654ee1b9ee7670718 100644
--- a/Sources/ScanFeature/Views/ScanOverlayView.swift
+++ b/Sources/ScanFeature/Views/ScanOverlayView.swift
@@ -1,181 +1,182 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ScanOverlayView: UIView {
-    private let cropView = UIView()
-    private let scanViewLength = 266.0
-    private let maskLayer = CAShapeLayer()
-    private let topLeftLayer = CAShapeLayer()
-    private let topRightLayer = CAShapeLayer()
-    private let bottomLeftLayer = CAShapeLayer()
-    private let bottomRightLayer = CAShapeLayer()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralDark.color.withAlphaComponent(0.5)
-
-        addSubview(cropView)
-
-        cropView.snp.makeConstraints {
-            $0.width.equalTo(scanViewLength)
-            $0.centerY.equalToSuperview().offset(-50)
-            $0.centerX.equalToSuperview()
-            $0.height.equalTo(scanViewLength)
-        }
-
-        maskLayer.fillRule = .evenOdd
-        layer.mask = maskLayer
-        layer.masksToBounds = true
-
-        [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
-            $0.strokeColor = Asset.brandPrimary.color.cgColor
-            $0.fillColor = UIColor.clear.cgColor
-            $0.lineWidth = 3.0
-            $0.lineCap = .round
-            layer.addSublayer($0)
-        }
+  private let cropView = UIView()
+  private let scanViewLength = 266.0
+  private let maskLayer = CAShapeLayer()
+  private let topLeftLayer = CAShapeLayer()
+  private let topRightLayer = CAShapeLayer()
+  private let bottomLeftLayer = CAShapeLayer()
+  private let bottomRightLayer = CAShapeLayer()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralDark.color.withAlphaComponent(0.5)
+
+    addSubview(cropView)
+
+    cropView.snp.makeConstraints {
+      $0.width.equalTo(scanViewLength)
+      $0.centerY.equalToSuperview().offset(-50)
+      $0.centerX.equalToSuperview()
+      $0.height.equalTo(scanViewLength)
     }
 
-    required init?(coder: NSCoder) { nil }
+    maskLayer.fillRule = .evenOdd
+    layer.mask = maskLayer
+    layer.masksToBounds = true
 
-    override func layoutSubviews() {
-        super.layoutSubviews()
-
-        maskLayer.frame = bounds
-        let path = UIBezierPath(rect: bounds)
-        path.append(UIBezierPath(roundedRect: cropView.frame, cornerRadius: 30.0))
-        maskLayer.path = path.cgPath
-
-        topLeftLayer.frame = bounds
-        topRightLayer.frame = bounds
-        bottomRightLayer.frame = bounds
-        bottomLeftLayer.frame = bounds
-
-        topLeftLayer.path = topLeftPath()
-        topRightLayer.path = topRightPath()
-        bottomRightLayer.path = bottomRightPath()
-        bottomLeftLayer.path = bottomLeftPath()
-    }
-
-    func updateCornerColor(_ color: UIColor) {
-        [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
-            $0.strokeColor = color.cgColor
-        }
-    }
-
-    func topLeftPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let vert0X = cropView.frame.minX - 15
-        let vert0Y = cropView.frame.minY + 45
-        let vert0 = CGPoint(x: vert0X, y: vert0Y)
-        path.move(to: vert0)
-
-        let vertNX = cropView.frame.minX - 15
-        let vertNY = cropView.frame.minY + 15
-        let vertN = CGPoint(x: vertNX, y: vertNY)
-        path.addLine(to: vertN)
-
-        let arcCenterX = cropView.frame.minX + 15
-        let arcCenterY = cropView.frame.minY + 15
-        let arcCenter = CGPoint(x: arcCenterX , y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: .pi)
-
-        let horizX = cropView.frame.minX + 45
-        let horizY = cropView.frame.minY - 15
-        let horiz = CGPoint(x: horizX, y: horizY)
-        path.addLine(to: horiz)
-
-        return path.cgPath
+    [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
+      $0.strokeColor = Asset.brandPrimary.color.cgColor
+      $0.fillColor = UIColor.clear.cgColor
+      $0.lineWidth = 3.0
+      $0.lineCap = .round
+      layer.addSublayer($0)
     }
+  }
 
-    func topRightPath() -> CGPath {
-        let path = UIBezierPath()
+  required init?(coder: NSCoder) { nil }
 
-        let horiz0X = cropView.frame.maxX - 45
-        let horiz0Y = cropView.frame.minY - 15
-        let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
-        path.move(to: horiz0)
+  override func layoutSubviews() {
+    super.layoutSubviews()
 
-        let horizNX = cropView.frame.maxX - 15
-        let horizNY = cropView.frame.minY - 15
-        let horizN = CGPoint(x: horizNX, y: horizNY)
-        path.addLine(to: horizN)
+    maskLayer.frame = bounds
+    let path = UIBezierPath(rect: bounds)
+    path.append(UIBezierPath(roundedRect: cropView.frame, cornerRadius: 30.0))
+    maskLayer.path = path.cgPath
 
-        let arcCenterX = cropView.frame.maxX - 15
-        let arcCenterY = cropView.frame.minY + 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: 3 * .pi/2)
+    topLeftLayer.frame = bounds
+    topRightLayer.frame = bounds
+    bottomRightLayer.frame = bounds
+    bottomLeftLayer.frame = bounds
 
-        let vertX = cropView.frame.maxX + 15
-        let vertY = cropView.frame.minY + 45
-        let vert = CGPoint(x: vertX, y: vertY)
-        path.addLine(to: vert)
+    topLeftLayer.path = topLeftPath()
+    topRightLayer.path = topRightPath()
+    bottomRightLayer.path = bottomRightPath()
+    bottomLeftLayer.path = bottomLeftPath()
+  }
 
-        return path.cgPath
-    }
-
-    func bottomRightPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let vert0X = cropView.frame.maxX + 15
-        let vert0Y = cropView.frame.maxY - 45
-        let vert0 = CGPoint(x: vert0X, y: vert0Y)
-        path.move(to: vert0)
-
-        let vertNX = cropView.frame.maxX + 15
-        let vertNY = cropView.frame.maxY - 15
-        let vertN = CGPoint(x: vertNX, y: vertNY)
-        path.addLine(to: vertN)
-
-        let arcCenterX = cropView.frame.maxX - 15
-        let arcCenterY = cropView.frame.maxY - 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: 0)
-
-        let horizX = cropView.frame.maxX - 45
-        let horizY = cropView.frame.maxY + 15
-        let horiz = CGPoint(x: horizX, y: horizY)
-        path.addLine(to: horiz)
-
-        return path.cgPath
-    }
-
-    func bottomLeftPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let horiz0X = cropView.frame.minX + 45
-        let horiz0Y = cropView.frame.maxY + 15
-        let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
-        path.move(to: horiz0)
-
-        let horizNX = cropView.frame.minX + 15
-        let horizNY = cropView.frame.maxY + 15
-        let horizN = CGPoint(x: horizNX, y: horizNY)
-        path.addLine(to: horizN)
-
-        let arcCenterX = cropView.frame.minX + 15
-        let arcCenterY = cropView.frame.maxY - 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: .pi/2)
-
-        let vertX = cropView.frame.minX - 15
-        let vertY = cropView.frame.maxY - 45
-        let vert = CGPoint(x: vertX, y: vertY)
-        path.addLine(to: vert)
-
-        return path.cgPath
+  func updateCornerColor(_ color: UIColor) {
+    [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
+      $0.strokeColor = color.cgColor
     }
+  }
+
+  func topLeftPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let vert0X = cropView.frame.minX - 15
+    let vert0Y = cropView.frame.minY + 45
+    let vert0 = CGPoint(x: vert0X, y: vert0Y)
+    path.move(to: vert0)
+
+    let vertNX = cropView.frame.minX - 15
+    let vertNY = cropView.frame.minY + 15
+    let vertN = CGPoint(x: vertNX, y: vertNY)
+    path.addLine(to: vertN)
+
+    let arcCenterX = cropView.frame.minX + 15
+    let arcCenterY = cropView.frame.minY + 15
+    let arcCenter = CGPoint(x: arcCenterX , y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: .pi)
+
+    let horizX = cropView.frame.minX + 45
+    let horizY = cropView.frame.minY - 15
+    let horiz = CGPoint(x: horizX, y: horizY)
+    path.addLine(to: horiz)
+
+    return path.cgPath
+  }
+
+  func topRightPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let horiz0X = cropView.frame.maxX - 45
+    let horiz0Y = cropView.frame.minY - 15
+    let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
+    path.move(to: horiz0)
+
+    let horizNX = cropView.frame.maxX - 15
+    let horizNY = cropView.frame.minY - 15
+    let horizN = CGPoint(x: horizNX, y: horizNY)
+    path.addLine(to: horizN)
+
+    let arcCenterX = cropView.frame.maxX - 15
+    let arcCenterY = cropView.frame.minY + 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: 3 * .pi/2)
+
+    let vertX = cropView.frame.maxX + 15
+    let vertY = cropView.frame.minY + 45
+    let vert = CGPoint(x: vertX, y: vertY)
+    path.addLine(to: vert)
+
+    return path.cgPath
+  }
+
+  func bottomRightPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let vert0X = cropView.frame.maxX + 15
+    let vert0Y = cropView.frame.maxY - 45
+    let vert0 = CGPoint(x: vert0X, y: vert0Y)
+    path.move(to: vert0)
+
+    let vertNX = cropView.frame.maxX + 15
+    let vertNY = cropView.frame.maxY - 15
+    let vertN = CGPoint(x: vertNX, y: vertNY)
+    path.addLine(to: vertN)
+
+    let arcCenterX = cropView.frame.maxX - 15
+    let arcCenterY = cropView.frame.maxY - 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: 0)
+
+    let horizX = cropView.frame.maxX - 45
+    let horizY = cropView.frame.maxY + 15
+    let horiz = CGPoint(x: horizX, y: horizY)
+    path.addLine(to: horiz)
+
+    return path.cgPath
+  }
+
+  func bottomLeftPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let horiz0X = cropView.frame.minX + 45
+    let horiz0Y = cropView.frame.maxY + 15
+    let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
+    path.move(to: horiz0)
+
+    let horizNX = cropView.frame.minX + 15
+    let horizNY = cropView.frame.maxY + 15
+    let horizN = CGPoint(x: horizNX, y: horizNY)
+    path.addLine(to: horizN)
+
+    let arcCenterX = cropView.frame.minX + 15
+    let arcCenterY = cropView.frame.maxY - 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: .pi/2)
+
+    let vertX = cropView.frame.minX - 15
+    let vertY = cropView.frame.maxY - 45
+    let vert = CGPoint(x: vertX, y: vertY)
+    path.addLine(to: vert)
+
+    return path.cgPath
+  }
 }
 
 private extension UIBezierPath {
-    func addArc(center: CGPoint, startAngle: CGFloat) {
-        addArc(
-            withCenter: center,
-            radius: 30,
-            startAngle: startAngle,
-            endAngle: startAngle + .pi/2,
-            clockwise: true
-        )
-    }
+  func addArc(center: CGPoint, startAngle: CGFloat) {
+    addArc(
+      withCenter: center,
+      radius: 30,
+      startAngle: startAngle,
+      endAngle: startAngle + .pi/2,
+      clockwise: true
+    )
+  }
 }
diff --git a/Sources/ScanFeature/Views/ScanQRButton.swift b/Sources/ScanFeature/Views/ScanQRButton.swift
index 66d911c602a67c4ad01a02002fc4f9de2b2563ac..35c045df11c1b3eb54da0360d653695d85a79e2b 100644
--- a/Sources/ScanFeature/Views/ScanQRButton.swift
+++ b/Sources/ScanFeature/Views/ScanQRButton.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ScanQRButton: UIControl {
     private let overlayView = UIView()
diff --git a/Sources/ScanFeature/Views/ScanSegmentedControlButton.swift b/Sources/ScanFeature/Views/ScanSegmentedControlButton.swift
index 85983848b9c60656f2f08944532e8c8b3553a165..010997ef1d52245501f61ec9a5fb1a8cb8381980 100644
--- a/Sources/ScanFeature/Views/ScanSegmentedControlButton.swift
+++ b/Sources/ScanFeature/Views/ScanSegmentedControlButton.swift
@@ -1,73 +1,74 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ScanSegmentedControlButton: UIControl {
-    let titleLabel = UILabel()
-    let separatorView = UIView()
-    let imageView = UIImageView()
+  let titleLabel = UILabel()
+  let separatorView = UIView()
+  let imageView = UIImageView()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        separatorView.alpha = 0.0
-        titleLabel.textAlignment = .center
-        imageView.tintColor = Asset.neutralWeak.color
-        titleLabel.textColor = Asset.neutralWeak.color
-        separatorView.backgroundColor = Asset.neutralWhite.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 13)
-        imageView.transform = imageView.transform.scaledBy(x: 0.9, y: 0.9)
-        titleLabel.transform = titleLabel.transform.scaledBy(x: 0.9, y: 0.9)
+    separatorView.alpha = 0.0
+    titleLabel.textAlignment = .center
+    imageView.tintColor = Asset.neutralWeak.color
+    titleLabel.textColor = Asset.neutralWeak.color
+    separatorView.backgroundColor = Asset.neutralWhite.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 13)
+    imageView.transform = imageView.transform.scaledBy(x: 0.9, y: 0.9)
+    titleLabel.transform = titleLabel.transform.scaledBy(x: 0.9, y: 0.9)
 
-        addSubview(titleLabel)
-        addSubview(imageView)
-        addSubview(separatorView)
+    addSubview(titleLabel)
+    addSubview(imageView)
+    addSubview(separatorView)
 
-        imageView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(7.5)
-            $0.centerX.equalToSuperview()
-        }
+    imageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(7.5)
+      $0.centerX.equalToSuperview()
+    }
 
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(imageView.snp.bottom).offset(2)
-            $0.centerX.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-7.5)
-        }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(imageView.snp.bottom).offset(2)
+      $0.centerX.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-7.5)
+    }
 
-        separatorView.snp.makeConstraints {
-            $0.height.equalTo(2)
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-            $0.bottom.equalToSuperview()
-        }
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(2)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+      $0.bottom.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func set(selected: Bool) {
-        switch (isSelected, selected) {
-        case (true, false):
-            UIView.animate(withDuration: 0.25) {
-                self.imageView.transform = self.imageView.transform.scaledBy(x: 0.9, y: 0.9)
-                self.titleLabel.transform = self.titleLabel.transform.scaledBy(x: 0.9, y: 0.9)
-                self.imageView.tintColor = Asset.neutralWeak.color
-                self.titleLabel.textColor = Asset.neutralWeak.color
-                self.separatorView.alpha = 0.0
-            } completion: { _ in
-                self.isSelected = false
-            }
+  func set(selected: Bool) {
+    switch (isSelected, selected) {
+    case (true, false):
+      UIView.animate(withDuration: 0.25) {
+        self.imageView.transform = self.imageView.transform.scaledBy(x: 0.9, y: 0.9)
+        self.titleLabel.transform = self.titleLabel.transform.scaledBy(x: 0.9, y: 0.9)
+        self.imageView.tintColor = Asset.neutralWeak.color
+        self.titleLabel.textColor = Asset.neutralWeak.color
+        self.separatorView.alpha = 0.0
+      } completion: { _ in
+        self.isSelected = false
+      }
 
-        case (false, true):
-            UIView.animate(withDuration: 0.25) {
-                self.imageView.transform = .identity
-                self.titleLabel.transform = .identity
-                self.imageView.tintColor = Asset.neutralWhite.color
-                self.titleLabel.textColor = Asset.neutralWhite.color
-                self.separatorView.alpha = 1.0
-            } completion: { _ in
-                self.isSelected = true
-            }
-        case (true, true), (false, false):
-            break
-        }
+    case (false, true):
+      UIView.animate(withDuration: 0.25) {
+        self.imageView.transform = .identity
+        self.titleLabel.transform = .identity
+        self.imageView.tintColor = Asset.neutralWhite.color
+        self.titleLabel.textColor = Asset.neutralWhite.color
+        self.separatorView.alpha = 1.0
+      } completion: { _ in
+        self.isSelected = true
+      }
+    case (true, true), (false, false):
+      break
     }
+  }
 }
diff --git a/Sources/ScanFeature/Views/ScanView.swift b/Sources/ScanFeature/Views/ScanView.swift
index 540f68f524bac7122bb0db21111c62e1aaddb454..8ae5933bf9a82d430ac0cd7cff31ec00faf5bee8 100644
--- a/Sources/ScanFeature/Views/ScanView.swift
+++ b/Sources/ScanFeature/Views/ScanView.swift
@@ -1,112 +1,113 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ScanView: UIView {
-    private let statusLabel = UILabel()
-    private let imageView = UIImageView()
-    private let stackView = UIStackView()
-    private let animationView = DotAnimation()
-    private let overlayView = ScanOverlayView()
-    private(set) var actionButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-        imageView.contentMode = .center
-        actionButton.setStyle(.brandColored)
-
-        statusLabel.numberOfLines = 0
-        statusLabel.textAlignment = .center
-        statusLabel.textColor = Asset.neutralWhite.color
-        statusLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        stackView.spacing = 15
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(animationView)
-        stackView.addArrangedSubview(imageView)
-        stackView.addArrangedSubview(statusLabel)
-        stackView.addArrangedSubview(actionButton)
-
-        imageView.isHidden = true
-        actionButton.isHidden = true
-        animationView.isHidden = false
-
-        addSubview(overlayView)
-        addSubview(stackView)
-
-        overlayView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        stackView.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(57)
-            $0.right.equalToSuperview().offset(-57)
-            $0.bottom.equalTo(safeAreaLayoutGuide).offset(-100)
-        }
+  private let statusLabel = UILabel()
+  private let imageView = UIImageView()
+  private let stackView = UIStackView()
+  private let animationView = DotAnimation()
+  private let overlayView = ScanOverlayView()
+  private(set) var actionButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+    imageView.contentMode = .center
+    actionButton.setStyle(.brandColored)
+
+    statusLabel.numberOfLines = 0
+    statusLabel.textAlignment = .center
+    statusLabel.textColor = Asset.neutralWhite.color
+    statusLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    stackView.spacing = 15
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(animationView)
+    stackView.addArrangedSubview(imageView)
+    stackView.addArrangedSubview(statusLabel)
+    stackView.addArrangedSubview(actionButton)
+
+    imageView.isHidden = true
+    actionButton.isHidden = true
+    animationView.isHidden = false
+
+    addSubview(overlayView)
+    addSubview(stackView)
+
+    overlayView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    func update(with state: ScanStatus) {
-        var text: String
-
-        switch state {
-        case .reading, .processing:
-            imageView.isHidden = true
-            actionButton.isHidden = true
-            text = Localized.Scan.Status.reading
-            overlayView.updateCornerColor(Asset.brandPrimary.color)
-
-        case .success:
-            animationView.isHidden = true
-            actionButton.isHidden = true
-            imageView.isHidden = false
-            imageView.image = Asset.sharedSuccess.image
-            text = Localized.Scan.Status.success
-            overlayView.updateCornerColor(Asset.accentSuccess.color)
-
-        case .failed(let error):
-            animationView.isHidden = true
-            imageView.image = Asset.scanError.image
-            imageView.isHidden = false
-            overlayView.updateCornerColor(Asset.accentDanger.color)
-
-            switch error {
-            case .requestOpened:
-                text = Localized.Scan.Error.requested
-                actionButton.setTitle(Localized.Scan.requests, for: .normal)
-                actionButton.isHidden = false
-
-            case .alreadyFriends(let name):
-                text = Localized.Scan.Error.alreadyFriends(name)
-                actionButton.setTitle(Localized.Scan.contact, for: .normal)
-                actionButton.isHidden = false
-
-            case .cameraPermission:
-                text = Localized.Scan.Error.cameraPermissionNeeded
-                actionButton.setTitle(Localized.Scan.settings, for: .normal)
-                actionButton.isHidden = false
-
-            case .unknown(let content):
-                text = content
-            }
-        }
-
-        let attString = NSMutableAttributedString(string: text)
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .center
-        paragraph.lineHeightMultiple = 1.35
-
-        attString.addAttribute(.paragraphStyle, value: paragraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralWhite.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.regular.font(size: 14.0) as Any)
-
-        if text.contains("#") {
-            attString.addAttribute(name: .foregroundColor, value: Asset.brandPrimary.color, betweenCharacters: "#")
-        }
-
-        statusLabel.attributedText = attString
+    stackView.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(57)
+      $0.right.equalToSuperview().offset(-57)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-100)
     }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func update(with state: ScanStatus) {
+    var text: String
+
+    switch state {
+    case .reading, .processing:
+      imageView.isHidden = true
+      actionButton.isHidden = true
+      text = Localized.Scan.Status.reading
+      overlayView.updateCornerColor(Asset.brandPrimary.color)
+
+    case .success:
+      animationView.isHidden = true
+      actionButton.isHidden = true
+      imageView.isHidden = false
+      imageView.image = Asset.sharedSuccess.image
+      text = Localized.Scan.Status.success
+      overlayView.updateCornerColor(Asset.accentSuccess.color)
+
+    case .failed(let error):
+      animationView.isHidden = true
+      imageView.image = Asset.scanError.image
+      imageView.isHidden = false
+      overlayView.updateCornerColor(Asset.accentDanger.color)
+
+      switch error {
+      case .requestOpened:
+        text = Localized.Scan.Error.requested
+        actionButton.setTitle(Localized.Scan.requests, for: .normal)
+        actionButton.isHidden = false
+
+      case .alreadyFriends(let name):
+        text = Localized.Scan.Error.alreadyFriends(name)
+        actionButton.setTitle(Localized.Scan.contact, for: .normal)
+        actionButton.isHidden = false
+
+      case .cameraPermission:
+        text = Localized.Scan.Error.cameraPermissionNeeded
+        actionButton.setTitle(Localized.Scan.settings, for: .normal)
+        actionButton.isHidden = false
+
+      case .unknown(let content):
+        text = content
+      }
+    }
+
+    let attString = NSMutableAttributedString(string: text)
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .center
+    paragraph.lineHeightMultiple = 1.35
+
+    attString.addAttribute(.paragraphStyle, value: paragraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralWhite.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.regular.font(size: 14.0) as Any)
+
+    if text.contains("#") {
+      attString.addAttribute(name: .foregroundColor, value: Asset.brandPrimary.color, betweenCharacters: "#")
+    }
+
+    statusLabel.attributedText = attString
+  }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift
index 8090af4f689290756de3a67082641cb099c37794..ec9bcd59eb990643390ba4d458c184d488b4d193 100644
--- a/Sources/SearchFeature/Controllers/SearchContainerController.swift
+++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift
@@ -1,14 +1,16 @@
 import UIKit
 import Shared
 import Combine
+import AppCore
 import XXModels
-import Navigation
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
 
 public final class SearchContainerController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var screenView = SearchContainerView()
 
@@ -39,7 +41,7 @@ public final class SearchContainerController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar.customize(
       backgroundColor: Asset.neutralWhite.color
     )
diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift
index 5570d6c5d349b6d0140e8290189e19f6aae5a017..4485fa22e286efcc668220c973c8aa4ab9ea0b3a 100644
--- a/Sources/SearchFeature/Controllers/SearchLeftController.swift
+++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift
@@ -3,13 +3,14 @@ import Shared
 import Combine
 import XXModels
 import Defaults
-import Navigation
+import AppResources
+import Dependencies
+import AppNavigation
 import DrawerFeature
 import CountryListFeature
-import DI
 
 final class SearchLeftController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
   @KeyObject(.sharingEmail, defaultValue: false) var isSharingEmail: Bool
diff --git a/Sources/SearchFeature/Controllers/SearchRightController.swift b/Sources/SearchFeature/Controllers/SearchRightController.swift
index 9f4a7f796111c96667da875b9a63baaedfffa116..3445f2266bc8a43dd479eb7cfe2bb9287e49e34b 100644
--- a/Sources/SearchFeature/Controllers/SearchRightController.swift
+++ b/Sources/SearchFeature/Controllers/SearchRightController.swift
@@ -1,10 +1,10 @@
 import UIKit
 import Combine
-import Navigation
-import DI
+import AppNavigation
+import ComposableArchitecture
 
 final class SearchRightController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = SearchRightView()
 
diff --git a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
index 7e5767a3a7180b1b554308c92067d0935a8bcb7b..1571afdae49af23f77a166b50518bffe21f92582 100644
--- a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
@@ -2,57 +2,50 @@ import UIKit
 import Combine
 import Defaults
 import XXClient
-import PushFeature
-import DI
+import PermissionsFeature
+import ComposableArchitecture
 
 final class SearchContainerViewModel {
-    @Dependency var pushHandler: PushHandling
-    @Dependency var dummyTrafficManager: DummyTraffic
-
-    @KeyObject(.dummyTrafficOn, defaultValue: false) var dummyTrafficOn
-    @KeyObject(.pushNotifications, defaultValue: false) var pushNotifications
-    @KeyObject(.askedDummyTrafficOnce, defaultValue: false) var offeredCoverTraffic
-
-    var coverTrafficPublisher: AnyPublisher<Void, Never> {
-        coverTrafficSubject.eraseToAnyPublisher()
-    }
-
-    private let coverTrafficSubject = PassthroughSubject<Void, Never>()
-
-    func didAppear() {
-        verifyCoverTraffic()
-        verifyNotifications()
-    }
-
-    func didEnableCoverTraffic() {
-        try! dummyTrafficManager.setStatus(true)
-        dummyTrafficOn = true
-    }
-
-    private func verifyCoverTraffic() {
-        guard offeredCoverTraffic == false else { return }
-        offeredCoverTraffic = true
-        coverTrafficSubject.send()
-    }
-
-    private func verifyNotifications() {
-        guard pushNotifications == false else { return }
-
-        pushHandler.requestAuthorization { [weak self] result in
-            guard let self else { return }
-
-            switch result {
-            case .success(let granted):
-                if granted {
-                    DispatchQueue.main.async {
-                        UIApplication.shared.registerForRemoteNotifications()
-                    }
-                }
-
-                self.pushNotifications = granted
-            case .failure:
-                self.pushNotifications = false
-            }
+  @Dependency(\.permissions) var permissions: PermissionsManager
+  //@Dependency(\.app.dummyTraffic) var dummyTraffic: DummyTraffic
+
+  @KeyObject(.dummyTrafficOn, defaultValue: false) var dummyTrafficOn
+  @KeyObject(.pushNotifications, defaultValue: false) var pushNotifications
+  @KeyObject(.askedDummyTrafficOnce, defaultValue: false) var offeredCoverTraffic
+
+  var coverTrafficPublisher: AnyPublisher<Void, Never> {
+    coverTrafficSubject.eraseToAnyPublisher()
+  }
+
+  private let coverTrafficSubject = PassthroughSubject<Void, Never>()
+
+  func didAppear() {
+    verifyCoverTraffic()
+    verifyNotifications()
+  }
+
+  func didEnableCoverTraffic() {
+//    try! dummyTraffic.setStatus(true)
+    dummyTrafficOn = true
+  }
+
+  private func verifyCoverTraffic() {
+    guard offeredCoverTraffic == false else { return }
+    offeredCoverTraffic = true
+    coverTrafficSubject.send()
+  }
+
+  private func verifyNotifications() {
+    guard pushNotifications == false else { return }
+
+    permissions.push.request { [weak self] granted in
+      guard let self else { return }
+      if granted == true {
+        DispatchQueue.main.async {
+          UIApplication.shared.registerForRemoteNotifications()
         }
+      }
+      self.pushNotifications = granted
     }
+  }
 }
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index f2c1c947e68275031b2a0d3c561d6fa6f662bd59..9a9aacb84b1b125233beb46f38601296a4f7df6d 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -6,11 +6,13 @@ import XXModels
 import XXClient
 import Defaults
 import CustomDump
+import AppResources
 import ReportingFeature
 import CombineSchedulers
 import XXMessengerClient
 import CountryListFeature
-import DI
+import Dependencies
+import AppCore
 
 typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>
 
@@ -22,12 +24,12 @@ struct SearchLeftViewState {
 }
 
 final class SearchLeftViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
-  @Dependency var reportingStatus: ReportingStatus
-  @Dependency var toastController: ToastController
-  @Dependency var networkMonitor: NetworkMonitoring
+  @Dependency(\.app.dbManager) var dbManager
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.app.hudManager) var hudManager
+  @Dependency(\.app.toastManager) var toastManager
+  @Dependency(\.reportingStatus) var reportingStatus
+  @Dependency(\.app.networkMonitor) var networkMonitor
 
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.sharingEmail, defaultValue: false) var sharingEmail: Bool
@@ -61,7 +63,7 @@ final class SearchLeftViewModel {
     if let pendingInvitation = invitation {
       invitation = nil
       stateSubject.value.input = pendingInvitation
-      hudController.show(.init(
+      hudManager.show(.init(
         actionTitle: Localized.Ud.Search.cancel,
         hasDotAnimation: true,
         onTapClosure: { [weak self] in
@@ -72,19 +74,19 @@ final class SearchLeftViewModel {
 
       networkCancellable.removeAll()
 
-      networkMonitor
-        .statusPublisher
-        .first { $0 == .available }
-        .eraseToAnyPublisher()
-        .flatMap { _ in
-          self.waitForNodes(timeout: 5)
-        }.sink(receiveCompletion: {
-          if case .failure(let error) = $0 {
-            self.hudController.show(.init(error: error))
-          }
-        }, receiveValue: {
-          self.didStartSearching()
-        }).store(in: &networkCancellable)
+//      networkMonitor
+//        .statusPublisher
+//        .first { $0 == .available }
+//        .eraseToAnyPublisher()
+//        .flatMap { _ in
+//          self.waitForNodes(timeout: 5)
+//        }.sink(receiveCompletion: {
+//          if case .failure(let error) = $0 {
+//            self.hudManager.show(.init(error: error))
+//          }
+//        }, receiveValue: {
+//          self.didStartSearching()
+//        }).store(in: &networkCancellable)
     }
   }
 
@@ -103,13 +105,13 @@ final class SearchLeftViewModel {
   func didTapCancelSearch() {
     searchCancellables.forEach { $0.cancel() }
     searchCancellables.removeAll()
-    hudController.dismiss()
+    hudManager.hide()
   }
 
   func didStartSearching() {
     guard stateSubject.value.input.isEmpty == false else { return }
 
-    hudController.show(.init(
+    hudManager.show(.init(
       actionTitle: Localized.Ud.Search.cancel,
       hasDotAnimation: true,
       onTapClosure: { [weak self] in
@@ -142,11 +144,11 @@ final class SearchLeftViewModel {
       guard let self else { return }
 
       if case .unhealthyNet = $0 as? NodeRegistrationError {
-        self.hudController.show(.init(content: "Network is not healthy yet, try again within the next minute or so."))
+        self.hudManager.show(.init(content: "Network is not healthy yet, try again within the next minute or so."))
       } else if case .belowMinimum = $0 as? NodeRegistrationError {
-        self.hudController.show(.init(content:"Node registration ratio is still below 80%, try again within the next minute or so."))
+        self.hudManager.show(.init(content:"Node registration ratio is still below 80%, try again within the next minute or so."))
       } else {
-        self.hudController.show(.init(error: $0))
+        self.hudManager.show(.init(error: $0))
       }
 
       return
@@ -173,7 +175,7 @@ final class SearchLeftViewModel {
           callback: .init(handle: {
             switch $0 {
             case .success(let results):
-              self.hudController.dismiss()
+              self.hudManager.hide()
               self.appendToLocalSearch(
                 XXModels.Contact(
                   id: try! results.first!.getId(),
@@ -194,7 +196,7 @@ final class SearchLeftViewModel {
               print(">>> SearchUD error: \(error.localizedDescription)")
 
               self.appendToLocalSearch(nil)
-              self.hudController.show(.init(error: error))
+              self.hudManager.show(.init(error: error))
             }
           })
         )
@@ -207,7 +209,7 @@ final class SearchLeftViewModel {
   }
 
   func didTapResend(contact: XXModels.Contact) {
-    hudController.show()
+    hudManager.show()
 
     var contact = contact
     contact.authStatus = .requesting
@@ -216,7 +218,7 @@ final class SearchLeftViewModel {
       guard let self else { return }
 
       do {
-        try self.database.saveContact(contact)
+        try self.dbManager.getDB().saveContact(contact)
 
         var includedFacts: [Fact] = []
         let myFacts = try self.messenger.ud.get()!.getFacts()
@@ -239,20 +241,20 @@ final class SearchLeftViewModel {
         )
 
         contact.authStatus = .requested
-        contact = try self.database.saveContact(contact)
+        contact = try self.dbManager.getDB().saveContact(contact)
 
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.presentSuccessToast(for: contact, resent: true)
       } catch {
         contact.authStatus = .requestFailed
-        _ = try? self.database.saveContact(contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
 
   func didTapRequest(contact: XXModels.Contact) {
-    hudController.show()
+    hudManager.show()
 
     var contact = contact
     contact.nickname = contact.username
@@ -262,7 +264,7 @@ final class SearchLeftViewModel {
       guard let self else { return }
 
       do {
-        try self.database.saveContact(contact)
+        try self.dbManager.getDB().saveContact(contact)
 
         var includedFacts: [Fact] = []
         let myFacts = try self.messenger.ud.get()!.getFacts()
@@ -285,23 +287,23 @@ final class SearchLeftViewModel {
         )
 
         contact.authStatus = .requested
-        contact = try self.database.saveContact(contact)
+        contact = try self.dbManager.getDB().saveContact(contact)
 
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.successSubject.send(contact)
         self.presentSuccessToast(for: contact, resent: false)
       } catch {
         contact.authStatus = .requestFailed
-        _ = try? self.database.saveContact(contact)
-        self.hudController.show(.init(error: error))
+        _ = try? self.dbManager.getDB().saveContact(contact)
+        self.hudManager.show(.init(error: error))
       }
     }
   }
 
   func didSet(nickname: String, for contact: XXModels.Contact) {
-    if var contact = try? database.fetchContacts(.init(id: [contact.id])).first {
+    if var contact = try? dbManager.getDB().fetchContacts(.init(id: [contact.id])).first {
       contact.nickname = nickname
-      _ = try? database.saveContact(contact)
+      _ = try? dbManager.getDB().saveContact(contact)
     }
   }
 
@@ -309,7 +311,7 @@ final class SearchLeftViewModel {
     var snapshot = SearchSnapshot()
 
     if var user = user {
-      if let contact = try? database.fetchContacts(.init(id: [user.id])).first {
+      if let contact = try? dbManager.getDB().fetchContacts(.init(id: [user.id])).first {
         user.isBanned = contact.isBanned
         user.isBlocked = contact.isBlocked
         user.authStatus = contact.authStatus
@@ -331,7 +333,7 @@ final class SearchLeftViewModel {
       isBanned: reportingStatus.isEnabled() ? false : nil
     )
 
-    if let locals = try? database.fetchContacts(localsQuery),
+    if let locals = try? dbManager.getDB().fetchContacts(localsQuery),
        let localsWithoutMe = removeMyself(from: locals),
        localsWithoutMe.isEmpty == false {
       snapshot.appendSections([.connections])
@@ -353,7 +355,7 @@ final class SearchLeftViewModel {
     let sentTitle = Localized.Requests.Sent.Toast.sent(name ?? "")
     let resentTitle = Localized.Requests.Sent.Toast.resent(name ?? "")
 
-    toastController.enqueueToast(model: .init(
+    toastManager.enqueue(.init(
       title: resent ? resentTitle : sentTitle,
       leftImage: Asset.sharedSuccess.image
     ))
diff --git a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
index 46d54a4603a40cb3be49785eb62b691b947473f2..12dab510ef00415aaa67d419f2f3c3e75000540e 100644
--- a/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchRightViewModel.swift
@@ -1,133 +1,135 @@
 import Shared
 import Combine
+import AppCore
 import XXModels
 import Defaults
 import XXClient
 import Foundation
-import Permissions
+import AppResources
 import ReportingFeature
 import XXMessengerClient
-import DI
+import PermissionsFeature
+import ComposableArchitecture
 
 enum ScanningStatus: Equatable {
-    case reading
-    case processing
-    case success
-    case failed(ScanningError)
+  case reading
+  case processing
+  case success
+  case failed(ScanningError)
 }
 
 enum ScanningError: Equatable {
-    case requestOpened
-    case unknown(String)
-    case cameraPermission
-    case alreadyFriends(String)
+  case requestOpened
+  case unknown(String)
+  case cameraPermission
+  case alreadyFriends(String)
 }
 
 final class SearchRightViewModel {
-    @Dependency var database: Database
-    @Dependency var permissions: PermissionHandling
-    @Dependency var reportingStatus: ReportingStatus
-
-    var foundPublisher: AnyPublisher<XXModels.Contact, Never> {
-        foundSubject.eraseToAnyPublisher()
-    }
-
-    var cameraSemaphorePublisher: AnyPublisher<Bool, Never> {
-        cameraSemaphoreSubject.eraseToAnyPublisher()
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.permissions) var permissions: PermissionsManager
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  var foundPublisher: AnyPublisher<XXModels.Contact, Never> {
+    foundSubject.eraseToAnyPublisher()
+  }
+
+  var cameraSemaphorePublisher: AnyPublisher<Bool, Never> {
+    cameraSemaphoreSubject.eraseToAnyPublisher()
+  }
+
+  var statusPublisher: AnyPublisher<ScanningStatus, Never> {
+    statusSubject.eraseToAnyPublisher()
+  }
+
+  private let foundSubject = PassthroughSubject<XXModels.Contact, Never>()
+  private let cameraSemaphoreSubject = PassthroughSubject<Bool, Never>()
+  private(set) var statusSubject = CurrentValueSubject<ScanningStatus, Never>(.reading)
+
+  func viewWillAppear() {
+    permissions.camera.request { [weak self] granted in
+      guard let self else { return }
+
+      if granted {
+        self.statusSubject.value = .reading
+        self.cameraSemaphoreSubject.send(true)
+      } else {
+        self.statusSubject.send(.failed(.cameraPermission))
+      }
     }
-
-    var statusPublisher: AnyPublisher<ScanningStatus, Never> {
-        statusSubject.eraseToAnyPublisher()
+  }
+
+  func viewWillDisappear() {
+    cameraSemaphoreSubject.send(false)
+  }
+
+  func didScan(data: Data) {
+    /// We need to be accepting new readings in order
+    /// to process what just got scanned.
+    ///
+    guard statusSubject.value == .reading else { return }
+    statusSubject.send(.processing)
+
+    /// Whatever got scanned, needs to have id and username
+    /// otherwise is just noise or an unknown qr code
+    ///
+    let user = XXClient.Contact.live(data)
+
+    guard
+      let uid = try? user.getId(),
+      let facts = try? user.getFacts(),
+      let username = facts.first(where: { $0.type == .username })?.value
+    else {
+      let errorTitle = Localized.Scan.Error.invalid
+      statusSubject.send(.failed(.unknown(errorTitle)))
+      return
     }
 
-    private let foundSubject = PassthroughSubject<XXModels.Contact, Never>()
-    private let cameraSemaphoreSubject = PassthroughSubject<Bool, Never>()
-    private(set) var statusSubject = CurrentValueSubject<ScanningStatus, Never>(.reading)
-
-    func viewWillAppear() {
-        permissions.requestCamera { [weak self] granted in
-            guard let self else { return }
-
-            if granted {
-                self.statusSubject.value = .reading
-                self.cameraSemaphoreSubject.send(true)
-            } else {
-                self.statusSubject.send(.failed(.cameraPermission))
-            }
-        }
+    let email = facts.first { $0.type == .email }?.value
+    let phone = facts.first { $0.type == .phone }?.value
+
+    /// Make sure we are not processing a contact
+    /// that we already have
+    ///
+    if let alreadyContact = try? dbManager.getDB().fetchContacts(.init(id: [uid])).first {
+      if alreadyContact.isBlocked, reportingStatus.isEnabled() {
+        statusSubject.send(.failed(.unknown("You previously blocked this user.")))
+        return
+      }
+
+      if alreadyContact.isBanned, reportingStatus.isEnabled() {
+        statusSubject.send(.failed(.unknown("This user was banned.")))
+        return
+      }
+
+      /// Show error accordingly to the auth status
+      ///
+      if alreadyContact.authStatus == .friend {
+        statusSubject.send(.failed(.alreadyFriends(username)))
+      } else if [.requested, .verified].contains(alreadyContact.authStatus) {
+        statusSubject.send(.failed(.requestOpened))
+      } else {
+        let generalErrorTitle = Localized.Scan.Error.general
+        statusSubject.send(.failed(.unknown(generalErrorTitle)))
+      }
+
+      return
     }
 
-    func viewWillDisappear() {
-        cameraSemaphoreSubject.send(false)
-    }
-
-    func didScan(data: Data) {
-        /// We need to be accepting new readings in order
-        /// to process what just got scanned.
-        ///
-        guard statusSubject.value == .reading else { return }
-        statusSubject.send(.processing)
-
-        /// Whatever got scanned, needs to have id and username
-        /// otherwise is just noise or an unknown qr code
-        ///
-        let user = XXClient.Contact.live(data)
-
-        guard
-            let uid = try? user.getId(),
-            let facts = try? user.getFacts(),
-            let username = facts.first(where: { $0.type == .username })?.value
-        else {
-            let errorTitle = Localized.Scan.Error.invalid
-            statusSubject.send(.failed(.unknown(errorTitle)))
-            return
-        }
-
-        let email = facts.first { $0.type == .email }?.value
-        let phone = facts.first { $0.type == .phone }?.value
-
-        /// Make sure we are not processing a contact
-        /// that we already have
-        ///
-        if let alreadyContact = try? database.fetchContacts(.init(id: [uid])).first {
-            if alreadyContact.isBlocked, reportingStatus.isEnabled() {
-                statusSubject.send(.failed(.unknown("You previously blocked this user.")))
-                return
-            }
-
-            if alreadyContact.isBanned, reportingStatus.isEnabled() {
-                statusSubject.send(.failed(.unknown("This user was banned.")))
-                return
-            }
-
-            /// Show error accordingly to the auth status
-            ///
-            if alreadyContact.authStatus == .friend {
-                statusSubject.send(.failed(.alreadyFriends(username)))
-            } else if [.requested, .verified].contains(alreadyContact.authStatus) {
-                statusSubject.send(.failed(.requestOpened))
-            } else {
-                let generalErrorTitle = Localized.Scan.Error.general
-                statusSubject.send(.failed(.unknown(generalErrorTitle)))
-            }
-
-            return
-        }
-
-        statusSubject.send(.success)
-        cameraSemaphoreSubject.send(false)
-
-        foundSubject.send(.init(
-            id: uid,
-            marshaled: data,
-            username: username,
-            email: email,
-            phone: phone,
-            nickname: nil,
-            photo: nil,
-            authStatus: .stranger,
-            isRecent: false,
-            createdAt: Date()
-        ))
-    }
+    statusSubject.send(.success)
+    cameraSemaphoreSubject.send(false)
+
+    foundSubject.send(.init(
+      id: uid,
+      marshaled: data,
+      username: username,
+      email: email,
+      phone: phone,
+      nickname: nil,
+      photo: nil,
+      authStatus: .stranger,
+      isRecent: false,
+      createdAt: Date()
+    ))
+  }
 }
diff --git a/Sources/SearchFeature/Views/OverlayView.swift b/Sources/SearchFeature/Views/OverlayView.swift
index 8242857716936fe49cf21a59bad280195c726165..4e85a3ea143885bd0ed21e1cb236c126a6ba9843 100644
--- a/Sources/SearchFeature/Views/OverlayView.swift
+++ b/Sources/SearchFeature/Views/OverlayView.swift
@@ -1,181 +1,182 @@
 import UIKit
 import Shared
+import AppResources
 
 final class OverlayView: UIView {
-    private let cropView = UIView()
-    private let scanViewLength = 266.0
-    private let maskLayer = CAShapeLayer()
-    private let topLeftLayer = CAShapeLayer()
-    private let topRightLayer = CAShapeLayer()
-    private let bottomLeftLayer = CAShapeLayer()
-    private let bottomRightLayer = CAShapeLayer()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralDark.color.withAlphaComponent(0.5)
-
-        addSubview(cropView)
-
-        cropView.snp.makeConstraints {
-            $0.width.equalTo(scanViewLength)
-            $0.centerY.equalToSuperview().offset(-50)
-            $0.centerX.equalToSuperview()
-            $0.height.equalTo(scanViewLength)
-        }
-
-        maskLayer.fillRule = .evenOdd
-        layer.mask = maskLayer
-        layer.masksToBounds = true
-
-        [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
-            $0.strokeColor = Asset.brandPrimary.color.cgColor
-            $0.fillColor = UIColor.clear.cgColor
-            $0.lineWidth = 3.0
-            $0.lineCap = .round
-            layer.addSublayer($0)
-        }
+  private let cropView = UIView()
+  private let scanViewLength = 266.0
+  private let maskLayer = CAShapeLayer()
+  private let topLeftLayer = CAShapeLayer()
+  private let topRightLayer = CAShapeLayer()
+  private let bottomLeftLayer = CAShapeLayer()
+  private let bottomRightLayer = CAShapeLayer()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralDark.color.withAlphaComponent(0.5)
+
+    addSubview(cropView)
+
+    cropView.snp.makeConstraints {
+      $0.width.equalTo(scanViewLength)
+      $0.centerY.equalToSuperview().offset(-50)
+      $0.centerX.equalToSuperview()
+      $0.height.equalTo(scanViewLength)
     }
 
-    required init?(coder: NSCoder) { nil }
+    maskLayer.fillRule = .evenOdd
+    layer.mask = maskLayer
+    layer.masksToBounds = true
 
-    override func layoutSubviews() {
-        super.layoutSubviews()
-
-        maskLayer.frame = bounds
-        let path = UIBezierPath(rect: bounds)
-        path.append(UIBezierPath(roundedRect: cropView.frame, cornerRadius: 30.0))
-        maskLayer.path = path.cgPath
-
-        topLeftLayer.frame = bounds
-        topRightLayer.frame = bounds
-        bottomRightLayer.frame = bounds
-        bottomLeftLayer.frame = bounds
-
-        topLeftLayer.path = topLeftPath()
-        topRightLayer.path = topRightPath()
-        bottomRightLayer.path = bottomRightPath()
-        bottomLeftLayer.path = bottomLeftPath()
-    }
-
-    func updateCornerColor(_ color: UIColor) {
-        [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
-            $0.strokeColor = color.cgColor
-        }
-    }
-
-    func topLeftPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let vert0X = cropView.frame.minX - 15
-        let vert0Y = cropView.frame.minY + 45
-        let vert0 = CGPoint(x: vert0X, y: vert0Y)
-        path.move(to: vert0)
-
-        let vertNX = cropView.frame.minX - 15
-        let vertNY = cropView.frame.minY + 15
-        let vertN = CGPoint(x: vertNX, y: vertNY)
-        path.addLine(to: vertN)
-
-        let arcCenterX = cropView.frame.minX + 15
-        let arcCenterY = cropView.frame.minY + 15
-        let arcCenter = CGPoint(x: arcCenterX , y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: .pi)
-
-        let horizX = cropView.frame.minX + 45
-        let horizY = cropView.frame.minY - 15
-        let horiz = CGPoint(x: horizX, y: horizY)
-        path.addLine(to: horiz)
-
-        return path.cgPath
+    [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
+      $0.strokeColor = Asset.brandPrimary.color.cgColor
+      $0.fillColor = UIColor.clear.cgColor
+      $0.lineWidth = 3.0
+      $0.lineCap = .round
+      layer.addSublayer($0)
     }
+  }
 
-    func topRightPath() -> CGPath {
-        let path = UIBezierPath()
+  required init?(coder: NSCoder) { nil }
 
-        let horiz0X = cropView.frame.maxX - 45
-        let horiz0Y = cropView.frame.minY - 15
-        let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
-        path.move(to: horiz0)
+  override func layoutSubviews() {
+    super.layoutSubviews()
 
-        let horizNX = cropView.frame.maxX - 15
-        let horizNY = cropView.frame.minY - 15
-        let horizN = CGPoint(x: horizNX, y: horizNY)
-        path.addLine(to: horizN)
+    maskLayer.frame = bounds
+    let path = UIBezierPath(rect: bounds)
+    path.append(UIBezierPath(roundedRect: cropView.frame, cornerRadius: 30.0))
+    maskLayer.path = path.cgPath
 
-        let arcCenterX = cropView.frame.maxX - 15
-        let arcCenterY = cropView.frame.minY + 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: 3 * .pi/2)
+    topLeftLayer.frame = bounds
+    topRightLayer.frame = bounds
+    bottomRightLayer.frame = bounds
+    bottomLeftLayer.frame = bounds
 
-        let vertX = cropView.frame.maxX + 15
-        let vertY = cropView.frame.minY + 45
-        let vert = CGPoint(x: vertX, y: vertY)
-        path.addLine(to: vert)
+    topLeftLayer.path = topLeftPath()
+    topRightLayer.path = topRightPath()
+    bottomRightLayer.path = bottomRightPath()
+    bottomLeftLayer.path = bottomLeftPath()
+  }
 
-        return path.cgPath
-    }
-
-    func bottomRightPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let vert0X = cropView.frame.maxX + 15
-        let vert0Y = cropView.frame.maxY - 45
-        let vert0 = CGPoint(x: vert0X, y: vert0Y)
-        path.move(to: vert0)
-
-        let vertNX = cropView.frame.maxX + 15
-        let vertNY = cropView.frame.maxY - 15
-        let vertN = CGPoint(x: vertNX, y: vertNY)
-        path.addLine(to: vertN)
-
-        let arcCenterX = cropView.frame.maxX - 15
-        let arcCenterY = cropView.frame.maxY - 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: 0)
-
-        let horizX = cropView.frame.maxX - 45
-        let horizY = cropView.frame.maxY + 15
-        let horiz = CGPoint(x: horizX, y: horizY)
-        path.addLine(to: horiz)
-
-        return path.cgPath
-    }
-
-    func bottomLeftPath() -> CGPath {
-        let path = UIBezierPath()
-
-        let horiz0X = cropView.frame.minX + 45
-        let horiz0Y = cropView.frame.maxY + 15
-        let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
-        path.move(to: horiz0)
-
-        let horizNX = cropView.frame.minX + 15
-        let horizNY = cropView.frame.maxY + 15
-        let horizN = CGPoint(x: horizNX, y: horizNY)
-        path.addLine(to: horizN)
-
-        let arcCenterX = cropView.frame.minX + 15
-        let arcCenterY = cropView.frame.maxY - 15
-        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
-        path.addArc(center: arcCenter, startAngle: .pi/2)
-
-        let vertX = cropView.frame.minX - 15
-        let vertY = cropView.frame.maxY - 45
-        let vert = CGPoint(x: vertX, y: vertY)
-        path.addLine(to: vert)
-
-        return path.cgPath
+  func updateCornerColor(_ color: UIColor) {
+    [topLeftLayer, topRightLayer, bottomLeftLayer, bottomRightLayer].forEach {
+      $0.strokeColor = color.cgColor
     }
+  }
+
+  func topLeftPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let vert0X = cropView.frame.minX - 15
+    let vert0Y = cropView.frame.minY + 45
+    let vert0 = CGPoint(x: vert0X, y: vert0Y)
+    path.move(to: vert0)
+
+    let vertNX = cropView.frame.minX - 15
+    let vertNY = cropView.frame.minY + 15
+    let vertN = CGPoint(x: vertNX, y: vertNY)
+    path.addLine(to: vertN)
+
+    let arcCenterX = cropView.frame.minX + 15
+    let arcCenterY = cropView.frame.minY + 15
+    let arcCenter = CGPoint(x: arcCenterX , y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: .pi)
+
+    let horizX = cropView.frame.minX + 45
+    let horizY = cropView.frame.minY - 15
+    let horiz = CGPoint(x: horizX, y: horizY)
+    path.addLine(to: horiz)
+
+    return path.cgPath
+  }
+
+  func topRightPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let horiz0X = cropView.frame.maxX - 45
+    let horiz0Y = cropView.frame.minY - 15
+    let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
+    path.move(to: horiz0)
+
+    let horizNX = cropView.frame.maxX - 15
+    let horizNY = cropView.frame.minY - 15
+    let horizN = CGPoint(x: horizNX, y: horizNY)
+    path.addLine(to: horizN)
+
+    let arcCenterX = cropView.frame.maxX - 15
+    let arcCenterY = cropView.frame.minY + 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: 3 * .pi/2)
+
+    let vertX = cropView.frame.maxX + 15
+    let vertY = cropView.frame.minY + 45
+    let vert = CGPoint(x: vertX, y: vertY)
+    path.addLine(to: vert)
+
+    return path.cgPath
+  }
+
+  func bottomRightPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let vert0X = cropView.frame.maxX + 15
+    let vert0Y = cropView.frame.maxY - 45
+    let vert0 = CGPoint(x: vert0X, y: vert0Y)
+    path.move(to: vert0)
+
+    let vertNX = cropView.frame.maxX + 15
+    let vertNY = cropView.frame.maxY - 15
+    let vertN = CGPoint(x: vertNX, y: vertNY)
+    path.addLine(to: vertN)
+
+    let arcCenterX = cropView.frame.maxX - 15
+    let arcCenterY = cropView.frame.maxY - 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: 0)
+
+    let horizX = cropView.frame.maxX - 45
+    let horizY = cropView.frame.maxY + 15
+    let horiz = CGPoint(x: horizX, y: horizY)
+    path.addLine(to: horiz)
+
+    return path.cgPath
+  }
+
+  func bottomLeftPath() -> CGPath {
+    let path = UIBezierPath()
+
+    let horiz0X = cropView.frame.minX + 45
+    let horiz0Y = cropView.frame.maxY + 15
+    let horiz0 = CGPoint(x: horiz0X, y: horiz0Y)
+    path.move(to: horiz0)
+
+    let horizNX = cropView.frame.minX + 15
+    let horizNY = cropView.frame.maxY + 15
+    let horizN = CGPoint(x: horizNX, y: horizNY)
+    path.addLine(to: horizN)
+
+    let arcCenterX = cropView.frame.minX + 15
+    let arcCenterY = cropView.frame.maxY - 15
+    let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
+    path.addArc(center: arcCenter, startAngle: .pi/2)
+
+    let vertX = cropView.frame.minX - 15
+    let vertY = cropView.frame.maxY - 45
+    let vert = CGPoint(x: vertX, y: vertY)
+    path.addLine(to: vert)
+
+    return path.cgPath
+  }
 }
 
 private extension UIBezierPath {
-    func addArc(center: CGPoint, startAngle: CGFloat) {
-        addArc(
-            withCenter: center,
-            radius: 30,
-            startAngle: startAngle,
-            endAngle: startAngle + .pi/2,
-            clockwise: true
-        )
-    }
+  func addArc(center: CGPoint, startAngle: CGFloat) {
+    addArc(
+      withCenter: center,
+      radius: 30,
+      startAngle: startAngle,
+      endAngle: startAngle + .pi/2,
+      clockwise: true
+    )
+  }
 }
diff --git a/Sources/SearchFeature/Views/SearchContainerView.swift b/Sources/SearchFeature/Views/SearchContainerView.swift
index 3a270bc5a52891fc915951bf68f738f2e5cdcd6f..878d438a464f7c22006518517f5f534f92c17a77 100644
--- a/Sources/SearchFeature/Views/SearchContainerView.swift
+++ b/Sources/SearchFeature/Views/SearchContainerView.swift
@@ -1,35 +1,32 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SearchContainerView: UIView {
-    let scrollView = UIScrollView()
-    let segmentedControl = SearchSegmentedControl()
+  let scrollView = UIScrollView()
+  let segmentedControl = SearchSegmentedControl()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        backgroundColor = Asset.neutralWhite.color
-        addSubview(segmentedControl)
-        addSubview(scrollView)
+    backgroundColor = Asset.neutralWhite.color
+    addSubview(segmentedControl)
+    addSubview(scrollView)
 
-        setupConstraints()
+    segmentedControl.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(10)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.height.equalTo(60)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    private func setupConstraints() {
-        segmentedControl.snp.makeConstraints {
-            $0.top.equalTo(safeAreaLayoutGuide).offset(10)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.height.equalTo(60)
-        }
-
-        scrollView.snp.makeConstraints {
-            $0.top.equalTo(segmentedControl.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    scrollView.snp.makeConstraints {
+      $0.top.equalTo(segmentedControl.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/SearchFeature/Views/SearchLeftEmptyView.swift b/Sources/SearchFeature/Views/SearchLeftEmptyView.swift
index 84c64c87a6096a16b2bbf793a9eadc1c95495324..4f33b053f0a104cd83a8d9c59e5ebbefdb40fc7b 100644
--- a/Sources/SearchFeature/Views/SearchLeftEmptyView.swift
+++ b/Sources/SearchFeature/Views/SearchLeftEmptyView.swift
@@ -1,26 +1,27 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SearchLeftEmptyView: UIView {
-    let titleLabel = UILabel()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        titleLabel.numberOfLines = 0
-        titleLabel.textAlignment = .center
-        titleLabel.font = Fonts.Mulish.regular.font(size: 15.0)
-        titleLabel.textColor = Asset.neutralSecondaryAlternative.color
-
-        addSubview(titleLabel)
-
-        titleLabel.snp.makeConstraints {
-            $0.center.equalToSuperview()
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-        }
+  let titleLabel = UILabel()
+  
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    
+    titleLabel.numberOfLines = 0
+    titleLabel.textAlignment = .center
+    titleLabel.font = Fonts.Mulish.regular.font(size: 15.0)
+    titleLabel.textColor = Asset.neutralSecondaryAlternative.color
+    
+    addSubview(titleLabel)
+    
+    titleLabel.snp.makeConstraints {
+      $0.center.equalToSuperview()
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
     }
-
-    required init?(coder: NSCoder) { nil }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift b/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
index 001c6687f16c73fab73f9c0bb2734b549a79d2ed..fa7f5c4fd37a6ade7e3105bf2f17fd3f45ab6938 100644
--- a/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
+++ b/Sources/SearchFeature/Views/SearchLeftPlaceholderView.swift
@@ -1,74 +1,75 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 final class SearchLeftPlaceholderView: UIView {
-    let titleLabel = UILabel()
-    let subtitleWithInfo = TextWithInfoView()
-
-    var infoPublisher: AnyPublisher<Void, Never> {
-        infoSubject.eraseToAnyPublisher()
-    }
-
-    private let infoSubject = PassthroughSubject<Void, Never>()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        let attrString = NSMutableAttributedString(
-            string: Localized.Ud.Search.Placeholder.title,
-            attributes: [
-                .foregroundColor: Asset.neutralDark.color,
-                .font: Fonts.Mulish.bold.font(size: 32.0)
-            ]
-        )
-
-        attrString.addAttribute(
-            name: .foregroundColor,
-            value: Asset.brandPrimary.color,
-            betweenCharacters: "#"
-        )
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attrString
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.lineHeightMultiple = 1.3
-
-        subtitleWithInfo.setup(
-            text: Localized.Ud.Search.Placeholder.subtitle,
-            attributes: [
-                .paragraphStyle: paragraph,
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0)
-            ],
-            didTapInfo: { [weak self] in
-                guard let self else { return }
-                self.infoSubject.send(())
-            }
-        )
-
-        addSubview(titleLabel)
-        addSubview(subtitleWithInfo)
-
-        setupConstraints()
+  let titleLabel = UILabel()
+  let subtitleWithInfo = TextWithInfoView()
+  
+  var infoPublisher: AnyPublisher<Void, Never> {
+    infoSubject.eraseToAnyPublisher()
+  }
+  
+  private let infoSubject = PassthroughSubject<Void, Never>()
+  
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+    
+    let attrString = NSMutableAttributedString(
+      string: Localized.Ud.Search.Placeholder.title,
+      attributes: [
+        .foregroundColor: Asset.neutralDark.color,
+        .font: Fonts.Mulish.bold.font(size: 32.0)
+      ]
+    )
+    
+    attrString.addAttribute(
+      name: .foregroundColor,
+      value: Asset.brandPrimary.color,
+      betweenCharacters: "#"
+    )
+    
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attrString
+    
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.lineHeightMultiple = 1.3
+    
+    subtitleWithInfo.setup(
+      text: Localized.Ud.Search.Placeholder.subtitle,
+      attributes: [
+        .paragraphStyle: paragraph,
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0)
+      ],
+      didTapInfo: { [weak self] in
+        guard let self else { return }
+        self.infoSubject.send(())
+      }
+    )
+    
+    addSubview(titleLabel)
+    addSubview(subtitleWithInfo)
+    
+    setupConstraints()
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  private func setupConstraints() {
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(50)
+      $0.left.equalToSuperview().offset(32.5)
+      $0.right.equalToSuperview().offset(-32.5)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setupConstraints() {
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(50)
-            $0.left.equalToSuperview().offset(32.5)
-            $0.right.equalToSuperview().offset(-32.5)
-        }
-
-        subtitleWithInfo.snp.makeConstraints {
-            $0.top.equalTo(titleLabel.snp.bottom).offset(30)
-            $0.left.equalToSuperview().offset(32.5)
-            $0.right.equalToSuperview().offset(-32.5)
-            $0.bottom.equalToSuperview()
-        }
+    
+    subtitleWithInfo.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(30)
+      $0.left.equalToSuperview().offset(32.5)
+      $0.right.equalToSuperview().offset(-32.5)
+      $0.bottom.equalToSuperview()
     }
+  }
 }
diff --git a/Sources/SearchFeature/Views/SearchLeftView.swift b/Sources/SearchFeature/Views/SearchLeftView.swift
index bbdda3f926818439e4c28d5beb020239a623048a..4eefca9a834265e687fee288e19a9a88689529d7 100644
--- a/Sources/SearchFeature/Views/SearchLeftView.swift
+++ b/Sources/SearchFeature/Views/SearchLeftView.swift
@@ -1,71 +1,72 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SearchLeftView: UIView {
-    let tableView = UITableView()
-    let inputStackView = UIStackView()
-    let inputField = SearchComponent()
-    let emptyView = SearchLeftEmptyView()
-    let countryButton = SearchCountryComponent()
-    let placeholderView = SearchLeftPlaceholderView()
+  let tableView = UITableView()
+  let inputStackView = UIStackView()
+  let inputField = SearchComponent()
+  let emptyView = SearchLeftEmptyView()
+  let countryButton = SearchCountryComponent()
+  let placeholderView = SearchLeftPlaceholderView()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        emptyView.isHidden = true
-        backgroundColor = Asset.neutralWhite.color
-        tableView.backgroundColor = Asset.neutralWhite.color
+    emptyView.isHidden = true
+    backgroundColor = Asset.neutralWhite.color
+    tableView.backgroundColor = Asset.neutralWhite.color
 
-        inputStackView.spacing = 5
-        inputStackView.addArrangedSubview(countryButton)
-        inputStackView.addArrangedSubview(inputField)
+    inputStackView.spacing = 5
+    inputStackView.addArrangedSubview(countryButton)
+    inputStackView.addArrangedSubview(inputField)
 
-        addSubview(inputStackView)
-        addSubview(tableView)
-        addSubview(emptyView)
-        addSubview(placeholderView)
+    addSubview(inputStackView)
+    addSubview(tableView)
+    addSubview(emptyView)
+    addSubview(placeholderView)
 
-        setupConstraints()
-    }
+    setupConstraints()
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func updateUIForItem(item: SearchSegmentedControl.Item) {
-        countryButton.isHidden = item != .phone
+  func updateUIForItem(item: SearchSegmentedControl.Item) {
+    countryButton.isHidden = item != .phone
 
-        let emptyTitle = Localized.Ud.Search.empty(item.written)
-        emptyView.titleLabel.text = emptyTitle
+    let emptyTitle = Localized.Ud.Search.empty(item.written)
+    emptyView.titleLabel.text = emptyTitle
 
-        let inputFieldTitle = Localized.Ud.Search.input(item.written)
-        inputField.set(placeholder: inputFieldTitle, imageAtRight: nil)
-    }
+    let inputFieldTitle = Localized.Ud.Search.input(item.written)
+    inputField.set(placeholder: inputFieldTitle, imageAtRight: nil)
+  }
 
-    private func setupConstraints() {
-        inputStackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(20)
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-        }
+  private func setupConstraints() {
+    inputStackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(20)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+    }
 
-        tableView.snp.makeConstraints {
-            $0.top.equalTo(inputField.snp.bottom).offset(20)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    tableView.snp.makeConstraints {
+      $0.top.equalTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
 
-        emptyView.snp.makeConstraints {
-            $0.top.equalTo(inputField.snp.bottom).offset(20)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    emptyView.snp.makeConstraints {
+      $0.top.equalTo(inputField.snp.bottom).offset(20)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
 
-        placeholderView.snp.makeConstraints {
-            $0.top.equalTo(inputField.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    placeholderView.snp.makeConstraints {
+      $0.top.equalTo(inputField.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
     }
+  }
 }
diff --git a/Sources/SearchFeature/Views/SearchRightView.swift b/Sources/SearchFeature/Views/SearchRightView.swift
index c2fd74760c79e8799c31bb91b0f73a85d4d5cd98..a374439fb729112f781ce56848daa2ebf78cf60d 100644
--- a/Sources/SearchFeature/Views/SearchRightView.swift
+++ b/Sources/SearchFeature/Views/SearchRightView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SearchRightView: UIView {
     let statusLabel = UILabel()
diff --git a/Sources/SearchFeature/Views/SearchSegmentedButton.swift b/Sources/SearchFeature/Views/SearchSegmentedButton.swift
index 3b8e65fb1b778703a748626155d6f2b0b18ec94b..ead382a4d69a9caab5e0e48fce4e7f89a1b737e7 100644
--- a/Sources/SearchFeature/Views/SearchSegmentedButton.swift
+++ b/Sources/SearchFeature/Views/SearchSegmentedButton.swift
@@ -1,49 +1,50 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SearchSegmentedButton: UIControl {
-    private let titleLabel = UILabel()
-    private let imageView = UIImageView()
-    private let highlightColor = Asset.brandPrimary.color
-    private let discreteColor = Asset.neutralDisabled.color
-
-    init() {
-        super.init(frame: .zero)
-
-        imageView.contentMode = .center
-        titleLabel.textAlignment = .center
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-
-        addSubview(titleLabel)
-        addSubview(imageView)
-
-        setupConstraints()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setup(title: String, icon: UIImage) {
-        imageView.image = icon
-        titleLabel.text = title
-        imageView.tintColor = discreteColor
-        titleLabel.textColor = discreteColor
-    }
-
-    func setSelected(_ bool: Bool) {
-        imageView.tintColor = bool ? highlightColor : discreteColor
-        titleLabel.textColor = bool ? highlightColor : discreteColor
+  private let titleLabel = UILabel()
+  private let imageView = UIImageView()
+  private let highlightColor = Asset.brandPrimary.color
+  private let discreteColor = Asset.neutralDisabled.color
+
+  init() {
+    super.init(frame: .zero)
+
+    imageView.contentMode = .center
+    titleLabel.textAlignment = .center
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+
+    addSubview(titleLabel)
+    addSubview(imageView)
+
+    setupConstraints()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setup(title: String, icon: UIImage) {
+    imageView.image = icon
+    titleLabel.text = title
+    imageView.tintColor = discreteColor
+    titleLabel.textColor = discreteColor
+  }
+
+  func setSelected(_ bool: Bool) {
+    imageView.tintColor = bool ? highlightColor : discreteColor
+    titleLabel.textColor = bool ? highlightColor : discreteColor
+  }
+
+  private func setupConstraints() {
+    imageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(7.5)
+      $0.centerX.equalToSuperview()
     }
 
-    private func setupConstraints() {
-        imageView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(7.5)
-            $0.centerX.equalToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(imageView.snp.bottom).offset(2)
-            $0.centerX.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-7.5)
-        }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(imageView.snp.bottom).offset(2)
+      $0.centerX.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-7.5)
     }
+  }
 }
diff --git a/Sources/SearchFeature/Views/SearchSegmentedControl.swift b/Sources/SearchFeature/Views/SearchSegmentedControl.swift
index 6141360378cd659e89dbdf67c4180f4a0e9b4ce6..94833095934ff15522cbf2f01255bdaaf652fb91 100644
--- a/Sources/SearchFeature/Views/SearchSegmentedControl.swift
+++ b/Sources/SearchFeature/Views/SearchSegmentedControl.swift
@@ -2,6 +2,7 @@ import UIKit
 import Shared
 import SnapKit
 import Combine
+import AppResources
 
 final class SearchSegmentedControl: UIView {
     enum Item: Int {
diff --git a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
index c4b434cda7e72f62b278ee82ac05da178f69ad92..96225a7dbebff485ce4289417abe0646150fc6f1 100644
--- a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
@@ -1,11 +1,11 @@
 import UIKit
-import Shared
 import Combine
-import Navigation
-import DI
+import Dependencies
+import AppResources
+import AppNavigation
 
 public final class SettingsAdvancedController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = SettingsAdvancedView()
 
diff --git a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift b/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift
similarity index 89%
rename from Sources/SettingsFeature/Controllers/AccountDeleteController.swift
rename to Sources/SettingsFeature/Controllers/SettingsDeleteController.swift
index 41fe4cacffab08c5fb743a4214493a5909b15e0f..0c64d28d92144c28ed4718a281b352f8ab749669 100644
--- a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsDeleteController.swift
@@ -2,19 +2,21 @@ import UIKit
 import Shared
 import Combine
 import Defaults
-import Navigation
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
 import ScrollViewController
-import DI
 
-public final class AccountDeleteController: UIViewController {
-  @Dependency var navigator: Navigator
+public final class SettingsDeleteController: UIViewController {
+  @Dependency(\.navigator) var navigator: Navigator
+
   @KeyObject(.username, defaultValue: "") var username: String
 
-  private lazy var screenView = AccountDeleteView()
+  private lazy var screenView = SettingsDeleteView()
   private lazy var scrollViewController = ScrollViewController()
 
-  private let viewModel = AccountDeleteViewModel()
+  private let viewModel = SettingsDeleteViewModel()
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
 
@@ -43,7 +45,9 @@ public final class AccountDeleteController: 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
diff --git a/Sources/SettingsFeature/Controllers/SettingsController.swift b/Sources/SettingsFeature/Controllers/SettingsMainController.swift
similarity index 95%
rename from Sources/SettingsFeature/Controllers/SettingsController.swift
rename to Sources/SettingsFeature/Controllers/SettingsMainController.swift
index 9186199140e0a55b37b2b48fd611cdd7b9afc795..574c0dca110aa011dd7643eae8e60a2b028827e5 100644
--- a/Sources/SettingsFeature/Controllers/SettingsController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsMainController.swift
@@ -1,17 +1,19 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppCore
+import Dependencies
+import AppResources
+import AppNavigation
 import DrawerFeature
-import DI
 import ScrollViewController
 
-public final class SettingsController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+public final class SettingsMainController: UIViewController {
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.app.statusBar) var statusBar: StatusBarStylist
 
   private lazy var scrollViewController = ScrollViewController()
-  private lazy var screenView = SettingsView {
+  private lazy var screenView = SettingsMainView {
     switch $0 {
     case .icognitoKeyboard:
       self.presentInfo(
@@ -39,13 +41,13 @@ public final class SettingsController: UIViewController {
     }
   }
 
-  private let viewModel = SettingsViewModel()
+  private let viewModel = SettingsMainViewModel()
   private var cancellables = Set<AnyCancellable>()
   private var drawerCancellables = Set<AnyCancellable>()
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.set(.darkContent)
     navigationController?.navigationBar
       .customize(backgroundColor: Asset.neutralWhite.color)
   }
@@ -192,7 +194,7 @@ public final class SettingsController: UIViewController {
       }.store(in: &cancellables)
 
     viewModel
-      .state
+      .statePublisher
       .map(\.isBiometricsPossible)
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
@@ -201,7 +203,7 @@ public final class SettingsController: UIViewController {
       }.store(in: &cancellables)
 
     viewModel
-      .state
+      .statePublisher
       .removeDuplicates()
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] state in
@@ -276,7 +278,7 @@ public final class SettingsController: UIViewController {
   }
 }
 
-extension SettingsController {
+extension SettingsMainController {
   private func presentInfo(
     title: String,
     subtitle: String,
diff --git a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
index 09985d189d79a3ded8e34a9506e07418833ee6cc..585880a067a7664e55035300cf9deeb2e15c0c70 100644
--- a/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsAdvancedViewModel.swift
@@ -1,10 +1,10 @@
 import Combine
-import XXLogger
+import AppCore
 import Defaults
 import Foundation
-import CrashReporting
+import CrashReport
 import ReportingFeature
-import DI
+import ComposableArchitecture
 
 struct AdvancedViewState: Equatable {
   var isRecordingLogs = false
@@ -21,14 +21,19 @@ final class SettingsAdvancedViewModel {
   private var cancellables = Set<AnyCancellable>()
   private let isShowingUsernamesKey = "isShowingUsernames"
 
-  @Dependency private var logger: XXLogger
-  @Dependency private var crashReporter: CrashReporter
-  @Dependency private var reportingStatus: ReportingStatus
+  @Dependency(\.app.log) var logger: Logger
+  @Dependency(\.crashReport) var crashReport: CrashReport
+  @Dependency(\.reportingStatus) var reportingStatus: ReportingStatus
+
+  var sharePublisher: AnyPublisher<URL, Never> {
+    shareRelay.eraseToAnyPublisher()
+  }
 
-  var sharePublisher: AnyPublisher<URL, Never> { shareRelay.eraseToAnyPublisher() }
   private let shareRelay = PassthroughSubject<URL, Never>()
 
-  var state: AnyPublisher<AdvancedViewState, Never> { stateRelay.eraseToAnyPublisher() }
+  var state: AnyPublisher<AdvancedViewState, Never> {
+    stateRelay.eraseToAnyPublisher()
+  }
   private let stateRelay = CurrentValueSubject<AdvancedViewState, Never>(.init())
 
   func loadCachedSettings() {
@@ -67,9 +72,9 @@ final class SettingsAdvancedViewModel {
 
   func didToggleRecordLogs() {
     if isRecordingLogs == true {
-      XXLogger.stop()
+//      XXLogger.stop()
     } else {
-      XXLogger.start()
+//      XXLogger.start()
     }
 
     isRecordingLogs.toggle()
@@ -84,7 +89,7 @@ final class SettingsAdvancedViewModel {
   func didToggleCrashReporting() {
     isCrashReporting.toggle()
     stateRelay.value.isCrashReporting.toggle()
-    crashReporter.setEnabled(isCrashReporting)
+    crashReport.setEnabled(isCrashReporting)
   }
 
   func didSetReporting(enabled: Bool) {
diff --git a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift
similarity index 55%
rename from Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
rename to Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift
index 08d8d5749bec6f760c604cb78543b0db248c3479..87dadb95c894fa10d06b82a53b094ccc04d00a67 100644
--- a/Sources/SettingsFeature/ViewModels/AccountDeleteViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsDeleteViewModel.swift
@@ -1,20 +1,15 @@
-import Retry
-import Shared
-import Combine
+import AppCore
 import Defaults
 import Keychain
-import XXModels
-import XXClient
 import Foundation
+import Dependencies
 import XXMessengerClient
-import DI
 
-final class AccountDeleteViewModel {
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var keychain: KeychainHandling
-  @Dependency var hudController: HUDController
-  
+final class SettingsDeleteViewModel {
+  @Dependency(\.keychain) var keychain: KeychainManager
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
   @KeyObject(.username, defaultValue: nil) var username: String?
 
   private var isCurrentlyDeleting = false
@@ -23,48 +18,38 @@ final class AccountDeleteViewModel {
     guard isCurrentlyDeleting == false else { return }
     isCurrentlyDeleting = true
 
-    hudController.show()
+    hudManager.show()
     
     do {
-      print(">>> try self.cleanUD()")
       try cleanUD()
-      
-      print(">>> try self.messenger.destroy()")
       try messenger.destroy()
-      
-      print(">>> try self.keychain.clear()")
-      try keychain.clear()
-      
-      print(">>> try database.drop()")
-      try database.drop()
-      
-      print(">>> try self.deleteDatabase()")
+      try keychain.destroy()
+      try dbManager.removeDB()
       try deleteDatabase()
       
       UserDefaults.resetStandardUserDefaults()
       UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
       UserDefaults.standard.synchronize()
       
-      hudController.show(.init(
+      hudManager.show(.init(
         title: "Account deleted",
         content: "Now kill the app and re-open"
       ))
     } catch {
       DispatchQueue.main.async { [weak self] in
         guard let self else { return }
-        self.hudController.show(.init(error: error))
+        self.hudManager.show(.init(error: error))
       }
     }
   }
   
   private func cleanUD() throws {
-    print(">>> Deleting my username (\(username ?? "NO_USERNAME")) from ud")
-    try messenger.ud.get()!.permanentDeleteAccount(username: .init(type: .username, value: username!))
+    try messenger.ud.get()!.permanentDeleteAccount(
+      username: .init(type: .username, value: username!)
+    )
   }
   
   private func deleteDatabase() throws {
-    print(">>> Deleting database...")
-    
     let dbPath = FileManager.default
       .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
       .appendingPathComponent("xxm_database")
diff --git a/Sources/SettingsFeature/ViewModels/SettingsMainViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsMainViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4fd4323dd0086207e7be26d2acd82bc117779a8b
--- /dev/null
+++ b/Sources/SettingsFeature/ViewModels/SettingsMainViewModel.swift
@@ -0,0 +1,128 @@
+import UIKit
+import AppCore
+import Combine
+import XXClient
+import Defaults
+import XXMessengerClient
+import PermissionsFeature
+import ComposableArchitecture
+
+final class SettingsMainViewModel {
+  struct ViewState: Equatable {
+    var isHideActiveApps: Bool = false
+    var isPushNotification: Bool = false
+    var isIcognitoKeyboard: Bool = false
+    var isInAppNotification: Bool = false
+    var isBiometricsEnabled: Bool = false
+    var isBiometricsPossible: Bool = false
+    var isDummyTrafficOn = false
+  }
+
+  @Dependency(\.app.bgQueue) var bgQueue
+  @Dependency(\.permissions) var permissions
+  @Dependency(\.app.messenger) var messenger
+  @Dependency(\.dummyTraffic) var dummyTraffic
+  @Dependency(\.app.hudManager) var hudManager
+
+  @KeyObject(.biometrics, defaultValue: false) var biometrics
+  @KeyObject(.hideAppList, defaultValue: false) var hideAppList
+  @KeyObject(.dummyTrafficOn, defaultValue: false) var dummyTrafficOn
+  @KeyObject(.icognitoKeyboard, defaultValue: false) var icognitoKeyboard
+  @KeyObject(.pushNotifications, defaultValue: false) var pushNotifications
+  @KeyObject(.inappnotifications, defaultValue: true) var inAppNotifications
+
+  var statePublisher: AnyPublisher<ViewState, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
+
+  func loadCachedSettings() {
+    stateSubject.value.isHideActiveApps = hideAppList
+    stateSubject.value.isBiometricsEnabled = biometrics
+    stateSubject.value.isIcognitoKeyboard = icognitoKeyboard
+    stateSubject.value.isPushNotification = pushNotifications
+    stateSubject.value.isInAppNotification = inAppNotifications
+    stateSubject.value.isBiometricsPossible = permissions.biometrics.status()
+    stateSubject.value.isDummyTrafficOn = dummyTraffic.get()!.getStatus()
+  }
+  
+  func didToggleBiometrics() {
+    biometricAuthentication(enable: !biometrics)
+  }
+  
+  func didToggleInAppNotifications() {
+    inAppNotifications.toggle()
+    stateSubject.value.isInAppNotification.toggle()
+  }
+  
+  func didTogglePushNotifications() {
+    pushNotifications(enable: !pushNotifications)
+  }
+  
+  func didToggleDummyTraffic() {
+    let currently = dummyTraffic.get()!.getStatus()
+    try! dummyTraffic.get()!.setStatus(!currently)
+    stateSubject.value.isDummyTrafficOn = !currently
+    dummyTrafficOn = stateSubject.value.isDummyTrafficOn
+  }
+
+  func didToggleHideActiveApps() {
+    hideAppList.toggle()
+    stateSubject.value.isHideActiveApps.toggle()
+  }
+
+  func didToggleIcognitoKeyboard() {
+    icognitoKeyboard.toggle()
+    stateSubject.value.isIcognitoKeyboard.toggle()
+  }
+
+  private func biometricAuthentication(enable: Bool) {
+    stateSubject.value.isBiometricsEnabled = enable
+
+    guard enable == true else {
+      biometrics = false
+      stateSubject.value.isBiometricsEnabled = false
+      return
+    }
+
+    permissions.biometrics.request { [weak self] in
+      guard let self else { return }
+      self.biometrics = $0
+      self.stateSubject.value.isBiometricsEnabled = $0
+    }
+  }
+  
+  private func pushNotifications(enable: Bool) {
+    hudManager.show()
+
+    if enable == true {
+      permissions.push.request { [weak self] granted in
+        guard let self else { return }
+        self.pushNotifications = granted
+        self.stateSubject.value.isPushNotification = granted
+        if granted {
+          DispatchQueue.main.async {
+            UIApplication.shared.registerForRemoteNotifications()
+          }
+        }
+        self.hudManager.hide()
+      }
+    } else {
+      bgQueue.schedule { [weak self] in
+        guard let self else { return }
+        do {
+          try UnregisterForNotifications.live(
+            e2eId: self.messenger.e2e.get()!.getId()
+          )
+          self.hudManager.hide()
+        } catch {
+          let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
+          self.hudManager.show(.init(content: xxError))
+        }
+        self.pushNotifications = false
+        self.stateSubject.value.isPushNotification = false
+      }
+    }
+  }
+}
diff --git a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
deleted file mode 100644
index f2fa2b54acb06a3836cdbc0021f6ce7423df5691..0000000000000000000000000000000000000000
--- a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
+++ /dev/null
@@ -1,150 +0,0 @@
-import UIKit
-import Shared
-import Combine
-import XXClient
-import Defaults
-import Permissions
-import PushFeature
-import XXMessengerClient
-import UserNotifications
-import CombineSchedulers
-import DI
-
-struct SettingsViewState: Equatable {
-  var isHideActiveApps: Bool = false
-  var isPushNotification: Bool = false
-  var isIcognitoKeyboard: Bool = false
-  var isInAppNotification: Bool = false
-  var isBiometricsEnabled: Bool = false
-  var isBiometricsPossible: Bool = false
-  var isDummyTrafficOn = false
-}
-
-final class SettingsViewModel {
-  @Dependency var messenger: Messenger
-  @Dependency var pushHandler: PushHandling
-  @Dependency var hudController: HUDController
-  @Dependency var permissions: PermissionHandling
-  @Dependency var dummyTrafficManager: DummyTraffic
-  
-  @KeyObject(.biometrics, defaultValue: false) var biometrics
-  @KeyObject(.hideAppList, defaultValue: false) var hideAppList
-  @KeyObject(.dummyTrafficOn, defaultValue: false) var dummyTrafficOn
-  @KeyObject(.icognitoKeyboard, defaultValue: false) var icognitoKeyboard
-  @KeyObject(.pushNotifications, defaultValue: false) var pushNotifications
-  @KeyObject(.inappnotifications, defaultValue: true) var inAppNotifications
-  
-  var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
-  
-  var state: AnyPublisher<SettingsViewState, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<SettingsViewState, Never>(.init())
-  
-  func loadCachedSettings() {
-    stateRelay.value.isHideActiveApps = hideAppList
-    stateRelay.value.isBiometricsEnabled = biometrics
-    stateRelay.value.isIcognitoKeyboard = icognitoKeyboard
-    stateRelay.value.isPushNotification = pushNotifications
-    stateRelay.value.isInAppNotification = inAppNotifications
-    stateRelay.value.isBiometricsPossible = permissions.isBiometricsAvailable
-    stateRelay.value.isDummyTrafficOn = dummyTrafficManager.getStatus()
-  }
-  
-  func didToggleBiometrics() {
-    biometricAuthentication(enable: !biometrics)
-  }
-  
-  func didToggleInAppNotifications() {
-    inAppNotifications.toggle()
-    stateRelay.value.isInAppNotification.toggle()
-  }
-  
-  func didTogglePushNotifications() {
-    pushNotifications(enable: !pushNotifications)
-  }
-  
-  func didToggleDummyTraffic() {
-    let currently = dummyTrafficManager.getStatus()
-    try! dummyTrafficManager.setStatus(!currently)
-    stateRelay.value.isDummyTrafficOn = !currently
-    dummyTrafficOn = stateRelay.value.isDummyTrafficOn
-  }
-  
-  func didToggleHideActiveApps() {
-    hideAppList.toggle()
-    stateRelay.value.isHideActiveApps.toggle()
-  }
-  
-  func didToggleIcognitoKeyboard() {
-    icognitoKeyboard.toggle()
-    stateRelay.value.isIcognitoKeyboard.toggle()
-  }
-
-  private func biometricAuthentication(enable: Bool) {
-    stateRelay.value.isBiometricsEnabled = enable
-    
-    guard enable == true else {
-      biometrics = false
-      stateRelay.value.isBiometricsEnabled = false
-      return
-    }
-    
-    permissions.requestBiometrics { [weak self] result in
-      guard let self else { return }
-      
-      switch result {
-      case .success(let granted):
-        if granted {
-          self.biometrics = true
-          self.stateRelay.value.isBiometricsEnabled = true
-        } else {
-          self.biometrics = false
-          self.stateRelay.value.isBiometricsEnabled = false
-        }
-      case .failure:
-        self.biometrics = false
-        self.stateRelay.value.isBiometricsEnabled = false
-      }
-    }
-  }
-  
-  private func pushNotifications(enable: Bool) {
-    hudController.show()
-    
-    if enable == true {
-      pushHandler.requestAuthorization { [weak self] result in
-        guard let self else { return }
-        
-        switch result {
-        case .success(let granted):
-          self.pushNotifications = granted
-          self.stateRelay.value.isPushNotification = granted
-          if granted {
-            DispatchQueue.main.async {
-              UIApplication.shared.registerForRemoteNotifications()
-            }
-          }
-          self.hudController.dismiss()
-        case .failure(let error):
-          self.hudController.show(.init(error: error))
-          self.pushNotifications = false
-          self.stateRelay.value.isPushNotification = false
-        }
-      }
-    } else {
-      backgroundScheduler.schedule { [weak self] in
-        guard let self else { return }
-        do {
-          try UnregisterForNotifications.live(
-            e2eId: self.messenger.e2e.get()!.getId()
-          )
-          self.hudController.dismiss()
-        } catch {
-          let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
-          self.hudController.show(.init(content: xxError))
-        }
-        self.pushNotifications = false
-        self.stateRelay.value.isPushNotification = false
-      }
-    }
-  }
-}
diff --git a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
index 750a175c208d29335c7c3354724de1b920c82d64..3d976f2505a4e8c23090724abdbbcd1a00fe70f5 100644
--- a/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
+++ b/Sources/SettingsFeature/Views/SettingsAdvancedView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SettingsAdvancedView: UIView {
   let stackView = UIStackView()
diff --git a/Sources/SettingsFeature/Views/AccountDeleteView.swift b/Sources/SettingsFeature/Views/SettingsDeleteView.swift
similarity index 98%
rename from Sources/SettingsFeature/Views/AccountDeleteView.swift
rename to Sources/SettingsFeature/Views/SettingsDeleteView.swift
index 791bec294559a098af1594448b41e0b30a7e4ad3..7ac68bccbbd95c0f299936ba726744fc3e26023b 100644
--- a/Sources/SettingsFeature/Views/AccountDeleteView.swift
+++ b/Sources/SettingsFeature/Views/SettingsDeleteView.swift
@@ -1,8 +1,9 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
-final class AccountDeleteView: UIView {
+final class SettingsDeleteView: UIView {
   let titleLabel = UILabel()
   let subtitleView = TextWithInfoView()
   let iconImageView = UIImageView()
diff --git a/Sources/SettingsFeature/Views/SettingsView.swift b/Sources/SettingsFeature/Views/SettingsMainView.swift
similarity index 98%
rename from Sources/SettingsFeature/Views/SettingsView.swift
rename to Sources/SettingsFeature/Views/SettingsMainView.swift
index 450e8aa60f347de50a3b9efc46316f9f73dbf81d..f1f84e5438f9a25b9fd823e4a53e3f37806e508d 100644
--- a/Sources/SettingsFeature/Views/SettingsView.swift
+++ b/Sources/SettingsFeature/Views/SettingsMainView.swift
@@ -1,7 +1,8 @@
 import UIKit
 import Shared
+import AppResources
 
-final class SettingsView: UIView {
+final class SettingsMainView: UIView {
   enum InfoTapped {
     case dummyTraffic
     case biometrics
diff --git a/Sources/SettingsFeature/Views/SettingsSwitcher.swift b/Sources/SettingsFeature/Views/SettingsSwitcher.swift
index 5a59b17fa3d7274215d498cd8d9ea050fc4201ee..8656cb7861506e22d51ff3dc22d7cde46ef3ac42 100644
--- a/Sources/SettingsFeature/Views/SettingsSwitcher.swift
+++ b/Sources/SettingsFeature/Views/SettingsSwitcher.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SettingsSwitcher: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/Shared/Aliases.swift b/Sources/Shared/Aliases.swift
deleted file mode 100644
index 6b3859ff2b6f5bdbc00a47fb1e352a7378868e04..0000000000000000000000000000000000000000
--- a/Sources/Shared/Aliases.swift
+++ /dev/null
@@ -1,4 +0,0 @@
-import UIKit
-
-public typealias EmptyClosure = () -> Void
-public typealias StringClosure = (String) -> Void
diff --git a/Sources/Shared/EditStateHandler.swift b/Sources/Shared/EditStateHandler.swift
index ca1fd06b2259b0cb3eafa4508cb0d8fab9ff9521..5b2407d8233a4b17797f43e8a285743e6bbe136e 100644
--- a/Sources/Shared/EditStateHandler.swift
+++ b/Sources/Shared/EditStateHandler.swift
@@ -1,12 +1,15 @@
 import Combine
 
 public final class EditStateHandler {
-  public var isEditing: AnyPublisher<Bool, Never> { stateRelay.eraseToAnyPublisher() }
-  private let stateRelay = CurrentValueSubject<Bool, Never>(false)
+  public var isEditing: AnyPublisher<Bool, Never> {
+    stateSubject.eraseToAnyPublisher()
+  }
+
+  private let stateSubject = CurrentValueSubject<Bool, Never>(false)
 
   public init() {}
 
   public func didSwitchEditing() {
-    stateRelay.value.toggle()
+    stateSubject.value.toggle()
   }
 }
diff --git a/Sources/Shared/Models/Payload.swift b/Sources/Shared/Models/Payload.swift
deleted file mode 100644
index eb7e67e3731adfcb6eb277fea1ede8554ed1cb60..0000000000000000000000000000000000000000
--- a/Sources/Shared/Models/Payload.swift
+++ /dev/null
@@ -1,37 +0,0 @@
-import Foundation
-
-public struct Payload: Codable, Equatable, Hashable {
-  public var text: String
-  public var reply: Reply?
-  
-  public init(text: String, reply: Reply?) {
-    self.text = text
-    self.reply = reply
-  }
-  
-  public init(with marshaled: Data) throws {
-    let proto = try CMIXText(serializedData: marshaled)
-    
-    var reply: Reply?
-    
-    if proto.hasReply {
-      reply = Reply(
-        messageId: proto.reply.messageID,
-        senderId: proto.reply.senderID
-      )
-    }
-    
-    self.init(text: proto.text, reply: reply)
-  }
-  
-  public func asData() -> Data {
-    var protoModel = CMIXText()
-    protoModel.text = text
-    
-    if let reply = reply {
-      protoModel.reply = reply.asTextReply()
-    }
-    
-    return try! protoModel.serializedData()
-  }
-}
diff --git a/Sources/Shared/Models/Reply.swift b/Sources/Shared/Models/Reply.swift
index edc61b01db652a5c57c93a4b893959655c7b37da..21ffda352cf1631cd638e6a66ef6248a6d55bd87 100644
--- a/Sources/Shared/Models/Reply.swift
+++ b/Sources/Shared/Models/Reply.swift
@@ -3,17 +3,17 @@ import Foundation
 public struct Reply: Codable, Equatable, Hashable {
   public let messageId: Data
   public let senderId: Data
-  
+
   public init(messageId: Data, senderId: Data) {
     self.messageId = messageId
     self.senderId = senderId
   }
-  
+
   func asTextReply() -> TextReply {
     var reply = TextReply()
     reply.messageID = messageId
     reply.senderID = senderId
-    
+
     return reply
   }
 }
diff --git a/Sources/StatusBarFeature/StatusBarDependency.swift b/Sources/StatusBarFeature/StatusBarDependency.swift
deleted file mode 100644
index 2d04e3932df4074598f04beeb297baed54cbaf50..0000000000000000000000000000000000000000
--- a/Sources/StatusBarFeature/StatusBarDependency.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import Dependencies
-
-private enum StatusBarDependencyKey: DependencyKey {
-  static let liveValue: StatusBarStyleManager = .live()
-  static let testValue: StatusBarStyleManager = .unimplemented
-}
-
-extension DependencyValues {
-  public var statusBar: StatusBarStyleManager {
-    get { self[StatusBarDependencyKey.self] }
-    set { self[StatusBarDependencyKey.self] = newValue }
-  }
-}
diff --git a/Sources/StatusBarFeature/StatusBarStyleFetch.swift b/Sources/StatusBarFeature/StatusBarStyleFetch.swift
deleted file mode 100644
index e57027ce0f9e9df7d87bf7e850ed06c2698d8a1a..0000000000000000000000000000000000000000
--- a/Sources/StatusBarFeature/StatusBarStyleFetch.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-import UIKit
-import XCTestDynamicOverlay
-
-public struct StatusBarStyleFetch {
-  public var run: () -> UIStatusBarStyle
-
-  public func callAsFunction() -> UIStatusBarStyle {
-    run()
-  }
-}
-
-extension StatusBarStyleFetch {
-  public static let unimplemented = StatusBarStyleFetch(
-    run: XCTUnimplemented("\(Self.self)")
-  )
-}
diff --git a/Sources/StatusBarFeature/StatusBarStyleManager.swift b/Sources/StatusBarFeature/StatusBarStyleManager.swift
deleted file mode 100644
index 3dbfe089beefd930fb13eafd35bea7fcd2734a3f..0000000000000000000000000000000000000000
--- a/Sources/StatusBarFeature/StatusBarStyleManager.swift
+++ /dev/null
@@ -1,39 +0,0 @@
-import UIKit
-import Combine
-import XCTestDynamicOverlay
-
-public struct StatusBarStyleManager {
-  public var update: StatusBarStyleUpdate
-  public var current: StatusBarStyleFetch
-  public var observe: StatusBarStyleObserve
-}
-
-extension StatusBarStyleManager {
-  public static func live() -> StatusBarStyleManager {
-    class Context {
-      let styleSubject = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
-    }
-
-    let context = Context()
-
-    return .init(
-      update: .init {
-        context.styleSubject.send($0)
-      },
-      current: .init {
-        context.styleSubject.value
-      },
-      observe: .init {
-        context.styleSubject.eraseToAnyPublisher()
-      }
-    )
-  }
-}
-
-extension StatusBarStyleManager {
-  public static let unimplemented = StatusBarStyleManager(
-    update: .unimplemented,
-    current: .unimplemented,
-    observe: .unimplemented
-  )
-}
diff --git a/Sources/StatusBarFeature/StatusBarStyleObserve.swift b/Sources/StatusBarFeature/StatusBarStyleObserve.swift
deleted file mode 100644
index 77c70223e0893b91a9df3b13365f76910adce573..0000000000000000000000000000000000000000
--- a/Sources/StatusBarFeature/StatusBarStyleObserve.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-import UIKit
-import Combine
-import XCTestDynamicOverlay
-
-public struct StatusBarStyleObserve {
-  public var run: () -> AnyPublisher<UIStatusBarStyle, Never>
-
-  public func callAsFunction() -> AnyPublisher<UIStatusBarStyle, Never> {
-    run()
-  }
-}
-
-extension StatusBarStyleObserve {
-  public static let unimplemented = StatusBarStyleObserve(
-    run: XCTUnimplemented("\(Self.self)")
-  )
-}
diff --git a/Sources/StatusBarFeature/StatusBarStyleUpdate.swift b/Sources/StatusBarFeature/StatusBarStyleUpdate.swift
deleted file mode 100644
index 95831faa90eb248a64de1e5e9b31b2d3d2820b8e..0000000000000000000000000000000000000000
--- a/Sources/StatusBarFeature/StatusBarStyleUpdate.swift
+++ /dev/null
@@ -1,16 +0,0 @@
-import UIKit
-import XCTestDynamicOverlay
-
-public struct StatusBarStyleUpdate {
-  public var run: (UIStatusBarStyle) -> Void
-
-  public func callAsFunction(_ style: UIStatusBarStyle) -> Void {
-    run(style)
-  }
-}
-
-extension StatusBarStyleUpdate {
-  public static let unimplemented = StatusBarStyleUpdate(
-    run: XCTUnimplemented("\(Self.self)")
-  )
-}
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
index 23fd543b54b13ff0599436d5e4301677795cab37..ce67d0e4e30f1de7a45b7013ab32615319dc799f 100644
--- a/Sources/TermsFeature/TermsConditionsController.swift
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -1,14 +1,14 @@
-import DI
 import UIKit
 import WebKit
 import Shared
 import Combine
 import Defaults
-import Navigation
 import AppResources
+import AppNavigation
+import ComposableArchitecture
 
 public final class TermsConditionsController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   @KeyObject(.username, defaultValue: nil) var username: String?
   @KeyObject(.acceptedTerms, defaultValue: false) var didAcceptTerms: Bool
@@ -72,12 +72,7 @@ public final class TermsConditionsController: UIViewController {
       .showTermsButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] _ in
-        let webView = WKWebView()
-        let webController = UIViewController()
-        webController.view.addSubview(webView)
-        webView.snp.makeConstraints { $0.edges.equalToSuperview() }
-        webView.load(URLRequest(url: URL(string: "https://elixxir.io/eula")!))
-        present(webController, animated: true)
+        navigator.perform(PresentWebsite(urlString: "https://elixxir.io/eula", from: self))
       }.store(in: &cancellables)
   }
 }
diff --git a/Sources/UpdateErrors/Dependency.swift b/Sources/UpdateErrors/Dependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7294a48614e8353a88079224bc6cf82f551517ee
--- /dev/null
+++ b/Sources/UpdateErrors/Dependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum UpdateErrorsDependencyKey: DependencyKey {
+  static let liveValue: UpdateErrors = .live
+  static let testValue: UpdateErrors = .unimplemented
+}
+
+extension DependencyValues {
+  public var updateErrors: UpdateErrors {
+    get { self[UpdateErrorsDependencyKey.self] }
+    set { self[UpdateErrorsDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/UpdateErrors/UpdateErrors.swift b/Sources/UpdateErrors/UpdateErrors.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6240d77c68672223e2ed8831fa85a876945bb1cf
--- /dev/null
+++ b/Sources/UpdateErrors/UpdateErrors.swift
@@ -0,0 +1,52 @@
+import XXClient
+import Foundation
+import XCTestDynamicOverlay
+
+public struct UpdateErrors {
+  public enum Error: Swift.Error {
+    case noData
+    case decodeFailure
+    case network(URLError)
+    case bindingsException
+  }
+
+  public typealias Completion = (Result<Void, Error>) -> Void
+
+  public var run: (@escaping Completion) -> Void
+
+  public func callAsFunction(_ completion: @escaping Completion) -> Void {
+    run(completion)
+  }
+}
+
+extension UpdateErrors {
+  public static let live = UpdateErrors { completion in
+    let url = URL(string: "https://git.xx.network/elixxir/client-error-database/-/raw/main/clientErrors.json")
+    URLSession.shared.dataTask(with: url!) { data, _, error in
+      if let error {
+        completion(.failure(.network(error as! URLError)))
+        return
+      }
+      guard let data else {
+        completion(.failure(.noData))
+        return
+      }
+      guard let string = String(data: data, encoding: .utf8) else {
+        completion(.failure(.decodeFailure))
+        return
+      }
+      do {
+        try UpdateCommonErrors.live(jsonFile: string)
+        completion(.success(()))
+      } catch {
+        completion(.failure(.bindingsException))
+      }
+    }.resume()
+  }
+}
+
+extension UpdateErrors {
+  public static let unimplemented = UpdateErrors(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/ChatInputFeature/Voxophone.swift b/Sources/Voxophone/Voxophone.swift
similarity index 100%
rename from Sources/ChatInputFeature/Voxophone.swift
rename to Sources/Voxophone/Voxophone.swift
diff --git a/Sources/WebsiteFeature/WebsiteController.swift b/Sources/WebsiteFeature/WebsiteController.swift
new file mode 100644
index 0000000000000000000000000000000000000000..822ebe38b883047de4c3f02157b883a2c0980bb6
--- /dev/null
+++ b/Sources/WebsiteFeature/WebsiteController.swift
@@ -0,0 +1,31 @@
+import UIKit
+import WebKit
+
+public final class WebsiteController: UIViewController {
+  private lazy var webView = WKWebView()
+
+  private let url: URL
+
+  public init(_ string: String) {
+    self.url = .init(string: string)!
+    super.init(nibName: nil, bundle: nil)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    view.backgroundColor = .white
+    view.addSubview(webView)
+
+    webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
+    webView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
+    webView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
+    webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
+
+    DispatchQueue.main.async { [weak self] in
+      guard let self else { return }
+      self.webView.load(URLRequest(url: self.url))
+    }
+  }
+}
diff --git a/Tests/DefaultsTests/KeyObjectTests.swift b/Tests/DefaultsTests/KeyObjectTests.swift
index 0cbf3b4fae776c082350548bd4fbf3b34232cdf4..e35e13ebf2d34edd1b5e5a3e2b1423699be7a21d 100644
--- a/Tests/DefaultsTests/KeyObjectTests.swift
+++ b/Tests/DefaultsTests/KeyObjectTests.swift
@@ -1,4 +1,3 @@
-import DI
 import XCTest
 
 @testable import Defaults
diff --git a/Tests/ThemeTests/ThemeTests.swift b/Tests/ThemeTests/ThemeTests.swift
index 1cc6794c92935ea93bf54b5a155075a88f58d0be..55049b48a6fdd1dd9bdc096336c1ca1da517f3a8 100644
--- a/Tests/ThemeTests/ThemeTests.swift
+++ b/Tests/ThemeTests/ThemeTests.swift
@@ -1,4 +1,3 @@
-import DI
 import Quick
 import Nimble
 import Defaults
diff --git a/XCFrameworks/Bindings.xcframework/Info.plist b/XCFrameworks/Bindings.xcframework/Info.plist
deleted file mode 100644
index 5da456bbdabbf3d610daca4ce17734b523413a53..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/Info.plist
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>AvailableLibraries</key>
-	<array>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64</string>
-			<key>LibraryPath</key>
-			<string>Bindings.framework</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-		</dict>
-		<dict>
-			<key>LibraryIdentifier</key>
-			<string>ios-arm64_x86_64-simulator</string>
-			<key>LibraryPath</key>
-			<string>Bindings.framework</string>
-			<key>SupportedArchitectures</key>
-			<array>
-				<string>arm64</string>
-				<string>x86_64</string>
-			</array>
-			<key>SupportedPlatform</key>
-			<string>ios</string>
-			<key>SupportedPlatformVariant</key>
-			<string>simulator</string>
-		</dict>
-	</array>
-	<key>CFBundlePackageType</key>
-	<string>XFWK</string>
-	<key>XCFrameworkFormatVersion</key>
-	<string>1.0</string>
-</dict>
-</plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Bindings
deleted file mode 100644
index 8d78f84d50a0b0719b795f7b342f6109c2b848ec..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Bindings
deleted file mode 100644
index 8d78f84d50a0b0719b795f7b342f6109c2b848ec..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/A/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Bindings
deleted file mode 100644
index 8d78f84d50a0b0719b795f7b342f6109c2b848ec..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64/Bindings.framework/Versions/Current/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Bindings
deleted file mode 100644
index 1e3b1dc25b4d65bf1e21a5d169dc3ae4de6c4fd7..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Bindings
deleted file mode 100644
index 1e3b1dc25b4d65bf1e21a5d169dc3ae4de6c4fd7..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/A/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Bindings b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Bindings
deleted file mode 100644
index 1e3b1dc25b4d65bf1e21a5d169dc3ae4de6c4fd7..0000000000000000000000000000000000000000
Binary files a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Bindings and /dev/null differ
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.h
deleted file mode 100644
index 8906a7da239705b790cb2bb64de92f806640cb38..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.h
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// Objective-C API for talking to the following Go packages
-//
-//	gitlab.com/elixxir/client/bindings
-//
-// File is generated by gomobile bind. Do not edit.
-#ifndef __Bindings_FRAMEWORK_H__
-#define __Bindings_FRAMEWORK_H__
-
-#include "Bindings.objc.h"
-#include "Universe.objc.h"
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.objc.h
deleted file mode 100644
index 32bf6d116888f787ced27b01b95cb4e1b2c1138b..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Bindings.objc.h
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Objective-C API for talking to gitlab.com/elixxir/client/bindings Go package.
-//   gobind -lang=objc gitlab.com/elixxir/client/bindings
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Bindings_H__
-#define __Bindings_H__
-
-@import Foundation;
-#include "ref.h"
-#include "Universe.objc.h"
-
-
-@class BindingsBackup;
-@class BindingsBackupReport;
-@class BindingsClient;
-@class BindingsContact;
-@class BindingsContactList;
-@class BindingsDummyTraffic;
-@class BindingsFact;
-@class BindingsFactList;
-@class BindingsFilePartTracker;
-@class BindingsFileTransfer;
-@class BindingsGroup;
-@class BindingsGroupChat;
-@class BindingsGroupMember;
-@class BindingsGroupMembership;
-@class BindingsGroupMessageReceive;
-@class BindingsGroupReportDisk;
-@class BindingsGroupSendReport;
-@class BindingsIdList;
-@class BindingsIntList;
-@class BindingsManyNotificationForMeReport;
-@class BindingsMessage;
-@class BindingsNewGroupReport;
-@class BindingsNodeRegistrationsStatus;
-@class BindingsNotificationForMeReport;
-@class BindingsRestoreContactsReport;
-@class BindingsRoundList;
-@class BindingsSendReport;
-@class BindingsSendReportDisk;
-@class BindingsUnregister;
-@class BindingsUser;
-@class BindingsUserDiscovery;
-@protocol BindingsAuthConfirmCallback;
-@class BindingsAuthConfirmCallback;
-@protocol BindingsAuthRequestCallback;
-@class BindingsAuthRequestCallback;
-@protocol BindingsAuthResetNotificationCallback;
-@class BindingsAuthResetNotificationCallback;
-@protocol BindingsClientError;
-@class BindingsClientError;
-@protocol BindingsEventCallbackFunctionObject;
-@class BindingsEventCallbackFunctionObject;
-@protocol BindingsFileTransferReceiveFunc;
-@class BindingsFileTransferReceiveFunc;
-@protocol BindingsFileTransferReceivedProgressFunc;
-@class BindingsFileTransferReceivedProgressFunc;
-@protocol BindingsFileTransferSentProgressFunc;
-@class BindingsFileTransferSentProgressFunc;
-@protocol BindingsGroupReceiveFunc;
-@class BindingsGroupReceiveFunc;
-@protocol BindingsGroupRequestFunc;
-@class BindingsGroupRequestFunc;
-@protocol BindingsListener;
-@class BindingsListener;
-@protocol BindingsLogWriter;
-@class BindingsLogWriter;
-@protocol BindingsLookupCallback;
-@class BindingsLookupCallback;
-@protocol BindingsMessageDeliveryCallback;
-@class BindingsMessageDeliveryCallback;
-@protocol BindingsMultiLookupCallback;
-@class BindingsMultiLookupCallback;
-@protocol BindingsNetworkHealthCallback;
-@class BindingsNetworkHealthCallback;
-@protocol BindingsPreimageNotification;
-@class BindingsPreimageNotification;
-@protocol BindingsRestoreContactsUpdater;
-@class BindingsRestoreContactsUpdater;
-@protocol BindingsRoundCompletionCallback;
-@class BindingsRoundCompletionCallback;
-@protocol BindingsRoundEventCallback;
-@class BindingsRoundEventCallback;
-@protocol BindingsSearchCallback;
-@class BindingsSearchCallback;
-@protocol BindingsSingleSearchCallback;
-@class BindingsSingleSearchCallback;
-@protocol BindingsTimeSource;
-@class BindingsTimeSource;
-@protocol BindingsUpdateBackupFunc;
-@class BindingsUpdateBackupFunc;
-
-@protocol BindingsAuthConfirmCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-@protocol BindingsAuthRequestCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsAuthResetNotificationCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@protocol BindingsClientError <NSObject>
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-@protocol BindingsEventCallbackFunctionObject <NSObject>
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-@protocol BindingsFileTransferReceiveFunc <NSObject>
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-@protocol BindingsFileTransferReceivedProgressFunc <NSObject>
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsFileTransferSentProgressFunc <NSObject>
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-@protocol BindingsGroupReceiveFunc <NSObject>
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-@protocol BindingsGroupRequestFunc <NSObject>
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-@protocol BindingsListener <NSObject>
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@protocol BindingsLogWriter <NSObject>
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-@protocol BindingsLookupCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsMessageDeliveryCallback <NSObject>
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-@protocol BindingsMultiLookupCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-@protocol BindingsNetworkHealthCallback <NSObject>
-- (void)callback:(BOOL)p0;
-@end
-
-@protocol BindingsPreimageNotification <NSObject>
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-@protocol BindingsRestoreContactsUpdater <NSObject>
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-@protocol BindingsRoundCompletionCallback <NSObject>
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsRoundEventCallback <NSObject>
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-@protocol BindingsSearchCallback <NSObject>
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsSingleSearchCallback <NSObject>
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@protocol BindingsTimeSource <NSObject>
-- (int64_t)nowMs;
-@end
-
-@protocol BindingsUpdateBackupFunc <NSObject>
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-@interface BindingsBackup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * AddJson stores a passed in json string in the backup structure
- */
-- (void)addJson:(NSString* _Nullable)json;
-/**
- * IsBackupRunning returns true if the backup has been initialized and is
-running. Returns false if it has been stopped.
- */
-- (BOOL)isBackupRunning;
-/**
- * StopBackup stops the backup processes and deletes the user's password from
-storage. To enable backups again, call InitializeBackup.
- */
-- (BOOL)stopBackup:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsBackupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field BackupReport.RestoredContacts with unsupported type: []*gitlab.com/xx_network/primitives/id.ID
-
-@property (nonatomic) NSString* _Nonnull params;
-@end
-
-/**
- * BindingsClient wraps the api.Client, implementing additional functions
-to support the gomobile Client interface
- */
-@interface BindingsClient : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)confirmAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteAllRequests clears all requests from Client's auth storage.
- */
-- (BOOL)deleteAllRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteContact is a function which removes a contact from Client's storage
- */
-- (BOOL)deleteContact:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteReceiveRequests clears receive requests from Client's auth storage.
- */
-- (BOOL)deleteReceiveRequests:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteRequest will delete a request, agnostic of request type
-for the given partner ID. If no request exists for this
-partner ID an error will be returned.
- */
-- (BOOL)deleteRequest:(NSData* _Nullable)requesterUserId error:(NSError* _Nullable* _Nullable)error;
-/**
- * DeleteSentRequests clears sent requests from Client's auth storage.
- */
-- (BOOL)deleteSentRequests:(NSError* _Nullable* _Nullable)error;
-// skipped method Client.GetInternalClient with unsupported parameter or return types
-
-/**
- * GetNodeRegistrationStatus returns a struct with the number of nodes the
-client is registered with and the number total.
- */
-- (BindingsNodeRegistrationsStatus* _Nullable)getNodeRegistrationStatus:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPartners returns a list of
- */
-- (NSData* _Nullable)getPartners:(NSError* _Nullable* _Nullable)error;
-/**
- * GetPreferredBins returns the geographic bin or bins that the provided two
-character country code is a part of. The bins are returned as CSV.
- */
-- (NSString* _Nonnull)getPreferredBins:(NSString* _Nullable)countryCode error:(NSError* _Nullable* _Nullable)error;
-- (NSString* _Nonnull)getPreimages:(NSData* _Nullable)identity;
-// skipped method Client.GetRateLimitParams with unsupported parameter or return types
-
-- (NSString* _Nonnull)getRelationshipFingerprint:(NSData* _Nullable)partnerID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Returns a user object from which all information about the current user
-can be gleaned
- */
-- (BindingsUser* _Nullable)getUser;
-/**
- * HasRunningProcessies checks if any background threads are running.
-returns true if none are running. This is meant to be
-used when NetworkFollowerStatus() returns Stopping.
-Due to the handling of comms on iOS, where the OS can
-block indefiently, it may not enter the stopped
-state apropreatly. This can be used instead.
- */
-- (BOOL)hasRunningProcessies;
-/**
- * returns true if the network is read to be in a healthy state where
-messages can be sent
- */
-- (BOOL)isNetworkHealthy;
-- (BindingsContact* _Nullable)makePrecannedAuthenticatedChannel:(long)precannedID error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the state of the network follower. Returns:
-Stopped 	- 0
-Starting - 1000
-Running	- 2000
-Stopping	- 3000
- */
-- (long)networkFollowerStatus;
-- (void)registerAuthCallbacks:(id<BindingsAuthRequestCallback> _Nullable)request confirm:(id<BindingsAuthConfirmCallback> _Nullable)confirm reset:(id<BindingsAuthResetNotificationCallback> _Nullable)reset;
-/**
- * RegisterClientErrorCallback registers the callback to handle errors from the
-long running threads controlled by StartNetworkFollower and StopNetworkFollower
- */
-- (void)registerClientErrorCallback:(id<BindingsClientError> _Nullable)clientError;
-/**
- * RegisterEventCallback records the given function to receive
-ReportableEvent objects. It returns the internal index
-of the callback so that it can be deleted later.
- */
-- (BOOL)registerEventCallback:(NSString* _Nullable)name myObj:(id<BindingsEventCallbackFunctionObject> _Nullable)myObj error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterForNotifications accepts firebase messaging token
- */
-- (BOOL)registerForNotifications:(NSString* _Nullable)token error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterListener records and installs a listener for messages
-matching specific uid, msgType, and/or username
-Returns a ListenerUnregister interface which can be
-
-to register for any userID, pass in an id with length 0 or an id with
-all zeroes
-
-to register for any message type, pass in a message type of 0
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsUnregister* _Nullable)registerListener:(NSData* _Nullable)uid msgType:(long)msgType listener:(id<BindingsListener> _Nullable)listener error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterNetworkHealthCB registers the network health callback to be called
-any time the network health changes. Returns a unique ID that can be used to
-unregister the network health callback.
- */
-- (int64_t)registerNetworkHealthCB:(id<BindingsNetworkHealthCallback> _Nullable)nhc;
-- (void)registerPreimageCallback:(NSData* _Nullable)identity pin:(id<BindingsPreimageNotification> _Nullable)pin;
-/**
- * RegisterRoundEventsHandler registers a callback interface for round
-events.
-The rid is the round the event attaches to
-The timeoutMS is the number of milliseconds until the event fails, and the
-validStates are a list of states (one per byte) on which the event gets
-triggered
-States:
- 0x00 - PENDING (Never seen by client)
- 0x01 - PRECOMPUTING
- 0x02 - STANDBY
- 0x03 - QUEUED
- 0x04 - REALTIME
- 0x05 - COMPLETED
- 0x06 - FAILED
-These states are defined in elixxir/primitives/states/state.go
- */
-- (BindingsUnregister* _Nullable)registerRoundEventsHandler:(long)rid cb:(id<BindingsRoundEventCallback> _Nullable)cb timeoutMS:(long)timeoutMS il:(BindingsIntList* _Nullable)il;
-- (void)replayRequests;
-- (BOOL)requestAuthenticatedChannel:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (BOOL)resetSession:(NSData* _Nullable)recipientMarshaled meMarshaled:(NSData* _Nullable)meMarshaled message:(NSString* _Nullable)message ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * This will return the round the message was sent on if it is successfully sent
-This can be used to register a round event to learn about message delivery.
-on failure a round id of -1 is returned
- */
-- (BOOL)sendCmix:(NSData* _Nullable)recipient contents:(NSData* _Nullable)contents parameters:(NSString* _Nullable)parameters ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendE2E sends an end-to-end payload to the provided recipient with
-the provided msgType. Returns the list of rounds in which parts of
-the message were sent or an error if it fails.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types
- */
-- (BindingsSendReport* _Nullable)sendE2E:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SendUnsafe sends an unencrypted payload to the provided recipient
-with the provided msgType. Returns the list of rounds in which parts
-of the message were sent or an error if it fails.
-NOTE: Do not use this function unless you know what you are doing.
-This function always produces an error message in client logging.
-
-Message Types can be found in client/interfaces/message/type.go
-Make sure to not conflict with ANY default message types with custom types
- */
-- (BindingsRoundList* _Nullable)sendUnsafe:(NSData* _Nullable)recipient payload:(NSData* _Nullable)payload messageType:(long)messageType parameters:(NSString* _Nullable)parameters error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetProxiedBins updates the host pool filter that filters out gateways that
-are not in one of the specified bins. The provided bins should be CSV.
- */
-- (BOOL)setProxiedBins:(NSString* _Nullable)binStringsCSV error:(NSError* _Nullable* _Nullable)error;
-/**
- * StartNetworkFollower kicks off the tracking of the network. It starts
-long running network client threads and returns an object for checking
-state and stopping those threads.
-Call this when returning from sleep and close when going back to
-sleep.
-These threads may become a significant drain on battery when offline, ensure
-they are stopped if there is no internet access
-Threads Started:
-  - Network Follower (/network/follow.go)
-  	tracks the network events and hands them off to workers for handling
-  - Historical Round Retrieval (/network/rounds/historical.go)
-		Retrieves data about rounds which are too old to be stored by the client
-	 - Message Retrieval Worker Group (/network/rounds/retrieve.go)
-		Requests all messages in a given round from the gateway of the last node
-	 - Message Handling Worker Group (/network/message/handle.go)
-		Decrypts and partitions messages when signals via the Switchboard
-	 - Health Tracker (/network/health)
-		Via the network instance tracks the state of the network
-	 - Garbled Messages (/network/message/garbled.go)
-		Can be signaled to check all recent messages which could be be decoded
-		Uses a message store on disk for persistence
-	 - Critical Messages (/network/message/critical.go)
-		Ensures all protocol layer mandatory messages are sent
-		Uses a message store on disk for persistence
-	 - KeyExchange Trigger (/keyExchange/trigger.go)
-		Responds to sent rekeys and executes them
-  - KeyExchange Confirm (/keyExchange/confirm.go)
-		Responds to confirmations of successful rekey operations
- */
-- (BOOL)startNetworkFollower:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * StopNetworkFollower stops the network follower if it is running.
-It returns errors if the Follower is in the wrong status to stop or if it
-fails to stop it.
-if the network follower is running and this fails, the client object will
-most likely be in an unrecoverable state and need to be trashed.
- */
-- (BOOL)stopNetworkFollower:(NSError* _Nullable* _Nullable)error;
-/**
- * UnregisterEventCallback deletes the callback identified by the
-index. It returns an error if it fails.
- */
-- (void)unregisterEventCallback:(NSString* _Nullable)name;
-/**
- * UnregisterForNotifications unregister user for notifications
- */
-- (BOOL)unregisterForNotifications:(NSError* _Nullable* _Nullable)error;
-- (void)unregisterNetworkHealthCB:(int64_t)funcID;
-- (BOOL)verifyOwnership:(NSData* _Nullable)receivedMarshaled verifiedMarshaled:(NSData* _Nullable)verifiedMarshaled ret0_:(BOOL* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForMessageDelivery allows the caller to get notified if the rounds a
-message was sent in successfully completed. Under the hood, this uses an API
-which uses the internal round data, network historical round lookup, and
-waiting on network events to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
-
-This function takes the marshaled send report to ensure a memory leak does
-not occur as a result of both sides of the bindings holding a reference to
-the same pointer.
- */
-- (BOOL)waitForMessageDelivery:(NSData* _Nullable)marshaledSendReport mdc:(id<BindingsMessageDeliveryCallback> _Nullable)mdc timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * WaitForNewtwork will block until either the network is healthy or the
-passed timeout. It will return true if the network is healthy
- */
-- (BOOL)waitForNetwork:(long)timeoutMS;
-/**
- * WaitForRoundCompletion allows the caller to get notified if a round
-has completed (or failed). Under the hood, this uses an API which uses the internal
-round data, network historical round lookup, and waiting on network events
-to determine what has (or will) occur.
-
-The callbacks will return at timeoutMS if no state update occurs
- */
-- (BOOL)waitForRoundCompletion:(long)roundID rec:(id<BindingsRoundCompletionCallback> _Nullable)rec timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- *  contact object
- */
-@interface BindingsContact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped method Contact.GetAPIContact with unsupported parameter or return types
-
-/**
- * GetDHPublicKey returns the public key associated with the Contact.
- */
-- (NSData* _Nullable)getDHPublicKey;
-/**
- * Returns a fact list for adding and getting facts to and from the contact
- */
-- (BindingsFactList* _Nullable)getFactList;
-/**
- * GetID returns the user ID for this user.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetDHPublicKey returns hash of a DH proof of key ownership.
- */
-- (NSData* _Nullable)getOwnershipProof;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsContactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BindingsContact* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * DummyTraffic contains the file dummy traffic manager. The manager can be used
-to set and get the status of the send thread.
- */
-@interface BindingsDummyTraffic : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client maxNumMessages:(long)maxNumMessages avgSendDeltaMS:(long)avgSendDeltaMS randomRangeMS:(long)randomRangeMS;
-/**
- * GetStatus returns the current state of the dummy traffic send thread. It has
-the following return values:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Note that this function does not return the status set by SetStatus directly;
-it returns the current status of the send thread, which means any call to
-SetStatus will have a small delay before it is returned by GetStatus.
- */
-- (BOOL)getStatus;
-/**
- * SetStatus sets the state of the dummy traffic send thread, which determines
-if the thread is running or paused. The possible statuses are:
- true  = send thread is sending dummy messages
- false = send thread is paused/stopped and not sending dummy messages
-Returns an error if the channel is full.
-Note that this function cannot change the status of the send thread if it has
-yet to be started or stopped.
- */
-- (BOOL)setStatus:(BOOL)status error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsFact : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-- (nullable instancetype)init:(long)factType factStr:(NSString* _Nullable)factStr;
-- (NSString* _Nonnull)get;
-- (NSString* _Nonnull)stringify;
-- (long)type;
-@end
-
-@interface BindingsFactList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * FactList
- */
-- (nullable instancetype)init;
-- (BOOL)add:(NSString* _Nullable)factData factType:(long)factType error:(NSError* _Nullable* _Nullable)error;
-- (BindingsFact* _Nullable)get:(long)i;
-- (long)num;
-- (NSString* _Nonnull)stringify:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * FilePartTracker contains the interfaces.FilePartTracker.
- */
-@interface BindingsFilePartTracker : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetNumParts returns the total number of file parts in the transfer.
- */
-- (long)getNumParts;
-/**
- * GetPartStatus returns the status of the file part with the given part number.
-The possible values for the status are:
-0 = unsent
-1 = sent (sender has sent a part, but it has not arrived)
-2 = arrived (sender has sent a part, and it has arrived)
-3 = received (receiver has received a part)
- */
-- (long)getPartStatus:(long)partNum;
-@end
-
-/**
- * FileTransfer contains the file transfer manager.
- */
-@interface BindingsFileTransfer : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-- (nullable instancetype)initManager:(BindingsClient* _Nullable)client receiveFunc:(id<BindingsFileTransferReceiveFunc> _Nullable)receiveFunc parameters:(NSString* _Nullable)parameters;
-/**
- * CloseSend deletes a sent file transfer from the sent transfer map and from
-storage once a transfer has completed or reached the retry limit. Returns an
-error if the transfer has not run out of retries.
- */
-- (BOOL)closeSend:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetMaxFileNameByteLength returns the maximum length, in bytes, allowed for a
-file name.
- */
-- (long)getMaxFileNameByteLength;
-/**
- * GetMaxFilePreviewSize returns the maximum file preview size, in bytes.
- */
-- (long)getMaxFilePreviewSize;
-/**
- * GetMaxFileSize returns the maximum file size, in bytes, allowed to be
-transferred.
- */
-- (long)getMaxFileSize;
-/**
- * GetMaxFileTypeByteLength returns the maximum length, in bytes, allowed for a
-file type.
- */
-- (long)getMaxFileTypeByteLength;
-/**
- * Receive returns the fully assembled file on the completion of the transfer.
-It deletes the transfer from the received transfer map and from storage.
-Returns an error if the transfer is not complete, the full file cannot be
-verified, or if the transfer cannot be found.
- */
-- (NSData* _Nullable)receive:(NSData* _Nullable)transferID error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterReceiveProgressCallback allows for the registration of a callback to
-track the progress of an individual received file transfer. The callback will
-be called immediately when added to report the current status of the
-transfer. It will then call every time a file part is received, the transfer
-completes, or an error occurs. It is called at most once ever period, which
-means if events occur faster than the period, then they will not be reported
-and instead, the progress will be reported once at the end of the period.
-Once the callback reports that the transfer has completed, the recipient
-can get the full file by calling Receive.
-The period is specified in milliseconds.
- */
-- (BOOL)registerReceiveProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferReceivedProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * RegisterSendProgressCallback allows for the registration of a callback to
-track the progress of an individual sent file transfer. The callback will be
-called immediately when added to report the current status of the transfer.
-It will then call every time a file part is sent, a file part arrives, the
-transfer completes, or an error occurs. It is called at most once every
-period, which means if events occur faster than the period, then they will
-not be reported and instead, the progress will be reported once at the end of
-the period.
-The period is specified in milliseconds.
- */
-- (BOOL)registerSendProgressCallback:(NSData* _Nullable)transferID progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends a file to the recipient. The sender must have an E2E relationship
-with the recipient.
-The file name is the name of the file to show a user. It has a max length of
-48 bytes.
-The file type identifies what type of file is being sent. It has a max length
-of 8 bytes.
-The file data cannot be larger than 256 kB
-The retry float is the total amount of data to send relative to the data
-size. Data will be resent on error and will resend up to [(1 + retry) *
-fileSize].
-The preview stores a preview of the data (such as a thumbnail) and is
-capped at 4 kB in size.
-Returns a unique transfer ID used to identify the transfer.
-PeriodMS is the duration, in milliseconds, to wait between progress callback
-calls. Set this large enough to prevent spamming.
- */
-- (NSData* _Nullable)send:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType fileData:(NSData* _Nullable)fileData recipientID:(NSData* _Nullable)recipientID retry:(float)retry preview:(NSData* _Nullable)preview progressFunc:(id<BindingsFileTransferSentProgressFunc> _Nullable)progressFunc periodMS:(long)periodMS error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Group structure contains the identifying and membership information of a
-group chat.
- */
-@interface BindingsGroup : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetCreatedMS returns the time the group was created in milliseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedMS;
-/**
- * GetCreatedNano returns the time the group was created in nanoseconds. This is
-also the time the group requests were sent.
- */
-- (int64_t)getCreatedNano;
-/**
- * GetID return the 33-byte unique group ID.
- */
-- (NSData* _Nullable)getID;
-/**
- * GetInitMessage returns initial message sent with the group request.
- */
-- (NSData* _Nullable)getInitMessage;
-/**
- * GetMembership returns a list of contacts, one for each member in the group.
-The list is in order; the first contact is the leader/creator of the group.
-All subsequent members are ordered by their ID.
- */
-- (BindingsGroupMembership* _Nullable)getMembership;
-/**
- * GetName returns the name set by the user for the group.
- */
-- (NSData* _Nullable)getName;
-/**
- * Serialize serializes the Group.
- */
-- (NSData* _Nullable)serialize;
-@end
-
-/**
- * GroupChat object contains the group chat manager.
- */
-@interface BindingsGroupChat : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetGroup returns the group with the group ID. If no group exists, then the
-error "failed to find group" is returned.
- */
-- (BindingsGroup* _Nullable)getGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * GetGroups returns an IdList containing a list of group IDs that the user is a
-part of.
- */
-- (BindingsIdList* _Nullable)getGroups;
-/**
- * JoinGroup allows a user to join a group when they receive a request. The
-caller must pass in the serialized bytes of a Group.
- */
-- (BOOL)joinGroup:(NSData* _Nullable)serializedGroupData error:(NSError* _Nullable* _Nullable)error;
-/**
- * LeaveGroup deletes a group so a user no longer has access.
- */
-- (BOOL)leaveGroup:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * MakeGroup creates a new group and sends a group request to all members in the
-group. The ID of the new group, the rounds the requests were sent on, and the
-status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)makeGroup:(BindingsIdList* _Nullable)membership name:(NSData* _Nullable)name message:(NSData* _Nullable)message;
-/**
- * NumGroups returns the number of groups the user is a part of.
- */
-- (long)numGroups;
-/**
- * ResendRequest resends a group request to all members in the group. The rounds
-they were sent on and the status of the send are contained in NewGroupReport.
- */
-- (BindingsNewGroupReport* _Nullable)resendRequest:(NSData* _Nullable)groupIdBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Send sends the message to the specified group. Returns the round the messages
-were sent on.
- */
-- (BindingsGroupSendReport* _Nullable)send:(NSData* _Nullable)groupIdBytes message:(NSData* _Nullable)message error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * //
-Member Structure
-//
-GroupMember represents a member in the group membership list.
- */
-@interface BindingsGroupMember : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMember.Member with unsupported type: gitlab.com/elixxir/crypto/group.Member
-
-// skipped method GroupMember.DeepCopy with unsupported parameter or return types
-
-// skipped method GroupMember.Equal with unsupported parameter or return types
-
-/**
- * GetDhKey returns the byte representation of the public Diffie–Hellman key of
-the member.
- */
-- (NSData* _Nullable)getDhKey;
-/**
- * GetID returns the 33-byte user ID of the member.
- */
-- (NSData* _Nullable)getID;
-- (NSString* _Nonnull)goString;
-- (NSData* _Nullable)serialize;
-- (NSString* _Nonnull)string;
-@end
-
-/**
- * GroupMembership structure contains a list of members that are part of a
-group. The first member is the group leader.
- */
-@interface BindingsGroupMembership : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Get returns the member at the index. The member at index 0 is always the
-group leader. An error is returned if the index is out of range.
- */
-- (BindingsGroupMember* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of members in the group membership.
- */
-- (long)len;
-@end
-
-/**
- * GroupMessageReceive contains a group message, its ID, and its data that a
-user receives.
- */
-@interface BindingsGroupMessageReceive : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupMessageReceive.MessageReceive with unsupported type: gitlab.com/elixxir/client/groupChat.MessageReceive
-
-/**
- * GetEphemeralID returns the ephemeral ID of the recipient.
- */
-- (int64_t)getEphemeralID;
-/**
- * GetGroupID returns the 33-byte group ID.
- */
-- (NSData* _Nullable)getGroupID;
-/**
- * GetMessageID returns the message ID.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetPayload returns the message payload.
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRecipientID returns the 33-byte user ID of the recipient.
- */
-- (NSData* _Nullable)getRecipientID;
-/**
- * GetRoundID returns the ID of the round the message was sent on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundTimestampMS returns the timestamp, in milliseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the timestamp, in nanoseconds, of the round the
-message was sent on.
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the ID of the round the message was sent on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSenderID returns the 33-byte user ID of the sender.
- */
-- (NSData* _Nullable)getSenderID;
-/**
- * GetTimestampMS returns the message timestamp in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message timestamp in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-- (NSString* _Nonnull)string;
-@end
-
-@interface BindingsGroupReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field GroupReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable grpId;
-@property (nonatomic) long status;
-@end
-
-/**
- * GroupSendReport is returned when sending a group message. It contains the
-round ID sent on and the timestamp of the send.
- */
-@interface BindingsGroupSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetMessageID returns the ID of the round that the send occurred on.
- */
-- (NSData* _Nullable)getMessageID;
-/**
- * GetRoundID returns the ID of the round that the send occurred on.
- */
-- (int64_t)getRoundID;
-/**
- * GetRoundURL returns the URL of the round that the send occurred on.
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the timestamp of the send in milliseconds.
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the timestamp of the send in nanoseconds.
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- *  ID list
-IdList contains a list of IDs.
- */
-@interface BindingsIdList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Add appends the ID bytes to the end of the list.
- */
-- (BOOL)add:(NSData* _Nullable)idBytes error:(NSError* _Nullable* _Nullable)error;
-/**
- * Get returns the ID at the index. An error is returned if the index is out of
-range.
- */
-- (NSData* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-/**
- * Len returns the number of IDs in the list.
- */
-- (long)len;
-@end
-
-@interface BindingsIntList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (void)add:(long)i;
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-@interface BindingsManyNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsNotificationForMeReport* _Nullable)get:(long)i error:(NSError* _Nullable* _Nullable)error;
-- (long)len;
-@end
-
-/**
- * Message is a message received from the cMix network in the clear
-or that has been decrypted using established E2E keys.
- */
-@interface BindingsMessage : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetID returns the id of the message
- */
-- (NSData* _Nullable)getID;
-/**
- * GetMessageType returns the message's type
- */
-- (long)getMessageType;
-/**
- * GetPayload returns the message's payload/contents
- */
-- (NSData* _Nullable)getPayload;
-/**
- * GetRoundId returns the message's round ID
- */
-- (int64_t)getRoundId;
-/**
- * GetRoundTimestampMS returns the message's round timestamp in milliseconds
- */
-- (int64_t)getRoundTimestampMS;
-/**
- * GetRoundTimestampNano returns the message's round timestamp in nanoseconds
- */
-- (int64_t)getRoundTimestampNano;
-/**
- * GetRoundURL returns the message's round URL
- */
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetSender returns the message's sender ID, if available
- */
-- (NSData* _Nullable)getSender;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-@end
-
-/**
- * NewGroupReport is returned when creating a new group and contains the ID of
-the group, a list of rounds that the group requests were sent on, and the
-status of the send.
- */
-@interface BindingsNewGroupReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetError returns the string of an error.
-Will be an empty string if no error occured
- */
-- (NSString* _Nonnull)getError;
-/**
- * GetGroup returns the Group.
- */
-- (BindingsGroup* _Nullable)getGroup;
-/**
- * GetRoundList returns the RoundList containing a list of rounds requests were
-sent on.
- */
-- (BindingsRoundList* _Nullable)getRoundList;
-/**
- * GetStatus returns the status of the requests sent when creating a new group.
-status = 0   an error occurred before any requests could be sent
-         1   all requests failed to send (call Resend Group)
-         2   some request failed and some succeeded (call Resend Group)
-         3,  all requests sent successfully (call Resend Group)
- */
-- (long)getStatus;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * NodeRegistrationsStatus structure for returning node registration statuses
-for bindings.
- */
-@interface BindingsNodeRegistrationsStatus : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetRegistered returns the number of nodes registered with the client.
- */
-- (long)getRegistered;
-/**
- * GetTotal return the total of nodes currently in the network.
- */
-- (long)getTotal;
-@end
-
-@interface BindingsNotificationForMeReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BOOL)forMe;
-- (NSData* _Nullable)source;
-- (NSString* _Nonnull)type;
-@end
-
-/**
- * RestoreContactsReport is a gomobile friendly report structure
-for determining which IDs restored, which failed, and why.
- */
-@interface BindingsRestoreContactsReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * GetErrorAt returns the error string at index
- */
-- (NSString* _Nonnull)getErrorAt:(long)index;
-/**
- * GetFailedAt returns the failed ID at index
- */
-- (NSData* _Nullable)getFailedAt:(long)index;
-/**
- * GetRestoreContactsError returns an error string. Empty if no error.
- */
-- (NSString* _Nonnull)getRestoreContactsError;
-/**
- * GetRestoredAt returns the restored ID at index
- */
-- (NSData* _Nullable)getRestoredAt:(long)index;
-/**
- * LenFailed returns the length of the ID's failed.
- */
-- (long)lenFailed;
-/**
- * LenRestored returns the length of ID's restored.
- */
-- (long)lenRestored;
-@end
-
-@interface BindingsRoundList : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Gets a stored round ID at the given index
- */
-- (BOOL)get:(long)i ret0_:(long* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
-/**
- * Gets the number of round IDs stored
- */
-- (long)len;
-@end
-
-/**
- * the send report is the mechanisim by which sendE2E returns a single
- */
-@interface BindingsSendReport : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (NSData* _Nullable)getMessageID;
-- (BindingsRoundList* _Nullable)getRoundList;
-- (NSString* _Nonnull)getRoundURL;
-/**
- * GetTimestampMS returns the message's timestamp in milliseconds
- */
-- (int64_t)getTimestampMS;
-/**
- * GetTimestampNano returns the message's timestamp in nanoseconds
- */
-- (int64_t)getTimestampNano;
-- (NSData* _Nullable)marshal:(NSError* _Nullable* _Nullable)error;
-- (BOOL)unmarshal:(NSData* _Nullable)b error:(NSError* _Nullable* _Nullable)error;
-@end
-
-@interface BindingsSendReportDisk : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-// skipped field SendReportDisk.List with unsupported type: []gitlab.com/xx_network/primitives/id.Round
-
-@property (nonatomic) NSData* _Nullable mid;
-@property (nonatomic) int64_t ts;
-@end
-
-/**
- * Generic Unregister - a generic return used for all callbacks which can be
-unregistered
-Interface which allows the un-registration of a listener
- */
-@interface BindingsUnregister : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-/**
- * Call unregisters a callback
- */
-- (void)unregister;
-@end
-
-@interface BindingsUser : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (nonnull instancetype)init;
-- (BindingsContact* _Nullable)getContact;
-- (NSData* _Nullable)getE2EDhPrivateKey;
-- (NSData* _Nullable)getE2EDhPublicKey;
-- (NSData* _Nullable)getReceptionID;
-- (NSData* _Nullable)getReceptionRSAPrivateKeyPem;
-- (NSData* _Nullable)getReceptionRSAPublicKeyPem;
-- (NSData* _Nullable)getReceptionSalt;
-- (NSData* _Nullable)getTransmissionID;
-- (NSData* _Nullable)getTransmissionRSAPrivateKeyPem;
-- (NSData* _Nullable)getTransmissionRSAPublicKeyPem;
-- (NSData* _Nullable)getTransmissionSalt;
-- (BOOL)isPrecanned;
-@end
-
-@interface BindingsUserDiscovery : NSObject <goSeqRefInterface> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)init:(BindingsClient* _Nullable)client;
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-- (nullable instancetype)initFromBackup:(BindingsClient* _Nullable)client email:(NSString* _Nullable)email phone:(NSString* _Nullable)phone;
-/**
- * AddFact adds a fact for the user to user discovery. Will only succeed if the
-user is already registered and the system does not have the fact currently
-registered for any user.
-Will fail if the fact string is not well formed.
-This does not complete the fact registration process, it returns a
-confirmation id instead. Over the communications system the fact is
-associated with, a code will be sent. This confirmation ID needs to be
-called along with the code to finalize the fact.
- */
-- (NSString* _Nonnull)addFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * ConfirmFact confirms a fact first registered via AddFact. The confirmation ID comes from
-AddFact while the code will come over the associated communications system
- */
-- (BOOL)confirmFact:(NSString* _Nullable)confirmationID code:(NSString* _Nullable)code error:(NSError* _Nullable* _Nullable)error;
-/**
- * Lookup the contact object associated with the given userID.  The
-id is the byte representation of an id.
-This will reject if that id is malformed. The LookupCallback will return
-the associated contact if it exists.
- */
-- (BOOL)lookup:(NSData* _Nullable)idBytes callback:(id<BindingsLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * MultiLookup Looks for the contact object associated with all given userIDs.
-The ids are the byte representation of an id stored in an IDList object.
-This will reject if that id is malformed or if the indexing on the IDList
-object is wrong. The MultiLookupCallback will return with all contacts
-returned within the timeout.
- */
-- (BOOL)multiLookup:(BindingsIdList* _Nullable)ids callback:(id<BindingsMultiLookupCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * Register registers a user with user discovery. Will return an error if the
-network signatures are malformed or if the username is taken. Usernames
-cannot be changed after registration at this time. Will fail if the user is
-already registered.
-Identity does not go over cmix, it occurs over normal communications
- */
-- (BOOL)register:(NSString* _Nullable)username error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveFact removes a previously confirmed fact.  Will fail if the passed fact string is
-not well-formed or if the fact is not associated with this client.
-Users cannot remove username facts and must instead remove the user.
- */
-- (BOOL)removeFact:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * RemoveUser deletes a user. The fact sent must be the username.
-This function preserves the username forever and makes it
-unusable.
- */
-- (BOOL)removeUser:(NSString* _Nullable)fStr error:(NSError* _Nullable* _Nullable)error;
-/**
- * Search for the passed Facts.  The factList is the stringification of a
-fact list object, look at /bindings/list.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This is NOT intended to be used to search for multiple users at once, that
-can have a privacy reduction. Instead, it is intended to be used to search
-for a user where multiple pieces of information is known.
- */
-- (BOOL)search:(NSString* _Nullable)fl callback:(id<BindingsSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SearchSingle searches for the passed Facts.  The fact is the stringification of a
-fact object, look at /bindings/contact.go for more on that object.
-This will reject if that object is malformed. The SearchCallback will return
-a list of contacts, each having the facts it hit against.
-This only searches for a single fact at a time. It is intended to make some
-simple use cases of the API easier.
- */
-- (BOOL)searchSingle:(NSString* _Nullable)f callback:(id<BindingsSingleSearchCallback> _Nullable)callback timeoutMS:(long)timeoutMS error:(NSError* _Nullable* _Nullable)error;
-/**
- * SetAlternativeUserDiscovery sets the alternativeUd object within manager.
-Once set, any user discovery operation will go through the alternative
-user discovery service.
-To undo this operation, use UnsetAlternativeUserDiscovery.
-The contact file is the already read in bytes, not the file path for the contact file.
- */
-- (BOOL)setAlternativeUserDiscovery:(NSData* _Nullable)address cert:(NSData* _Nullable)cert contactFile:(NSData* _Nullable)contactFile error:(NSError* _Nullable* _Nullable)error;
-/**
- * UnsetAlternativeUserDiscovery clears out the information from
-the Manager object.
- */
-- (BOOL)unsetAlternativeUserDiscovery:(NSError* _Nullable* _Nullable)error;
-@end
-
-/**
- * Error codes
- */
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedCode;
-FOUNDATION_EXPORT NSString* _Nonnull const BindingsUnrecognizedMessage;
-
-/**
- * CompressJpeg takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpeg(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * CompressJpegForPreview takes a JPEG image in byte format
-and compresses it based on desired output size
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsCompressJpegForPreview(NSData* _Nullable imgBytes, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadAndVerifySignedNdfWithUrl retrieves the NDF from a specified URL.
-The NDF is processed into a protobuf containing a signature which
-is verified using the cert string passed in. The NDF is returned as marshaled
-byte data which may be used to start a client.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadAndVerifySignedNdfWithUrl(NSString* _Nullable url, NSString* _Nullable cert, NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadDAppRegistrationDB returns a []byte containing
-the JSON data describing registered dApps.
-See https://git.xx.network/elixxir/registered-dapps
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadDAppRegistrationDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DownloadErrorDB returns a []byte containing the JSON data
-describing client errors.
-See https://git.xx.network/elixxir/client-error-database/
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsDownloadErrorDB(NSError* _Nullable* _Nullable error);
-
-/**
- * DumpStack returns a string with the stack trace of every running thread.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsDumpStack(NSError* _Nullable* _Nullable error);
-
-/**
- * EnableGrpcLogs sets GRPC trace logging
- */
-FOUNDATION_EXPORT void BindingsEnableGrpcLogs(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * ErrorStringToUserFriendlyMessage takes a passed in errStr which will be
-a backend generated error. These may be error specifically written by
-the backend team or lower level errors gotten from low level dependencies.
-This function will parse the error string for common errors provided from
-errToUserErr to provide a more user-friendly error message for the front end.
-If the error is not common, some simple parsing is done on the error message
-to make it more user-accessible, removing backend specific jargon.
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsErrorStringToUserFriendlyMessage(NSString* _Nullable errStr);
-
-/**
- * GenerateSecret creates a secret password using a system-based
-pseudorandom number generator. It takes 1 parameter, `numBytes`,
-which should be set to 32, but can be set higher in certain cases.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsGenerateSecret(long numBytes);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetCMIXParams(NSError* _Nullable* _Nullable error);
-
-/**
- * returns a previously created client. IF be used if the garbage collector
-removes the client instance on the app side.  Is NOT thread safe relative to
-login, newClient, or newPrecannedClient
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsGetClientSingleton(void);
-
-/**
- * GetDependencies returns the api DEPENDENCIES
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetDependencies(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetE2EParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetGitVersion rturns the api GITVERSION
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetGitVersion(void);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetNetworkParams(NSError* _Nullable* _Nullable error);
-
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetUnsafeParams(NSError* _Nullable* _Nullable error);
-
-/**
- * GetVersion returns the api SEMVER
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsGetVersion(void);
-
-/**
- * InitializeBackup starts the backup processes that returns backup updates when
-they occur. Any time an event occurs that changes the contents of the backup,
-such as adding or deleting a contact, the backup is triggered and an
-encrypted backup is generated and returned on the updateBackupCb callback.
-Call this function only when enabling backup if it has not already been
-initialized or when the user wants to change their password.
-To resume backup process on app recovery, use ResumeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsInitializeBackup(NSString* _Nullable password, id<BindingsUpdateBackupFunc> _Nullable updateBackupCb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * LoadSecretWithMnemonic loads the secret stored from the call to
-StoreSecretWithMnemonic. The path given should be the same filepath
-as the path given in StoreSecretWithMnemonic. There should be a file
-in this path called ".recovery". This operation is not tied
-to client operations, as the user will not have a client when trying to
-recover their account.
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsLoadSecretWithMnemonic(NSString* _Nullable mnemonic, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * sets level of logging. All logs the set level and above will be displayed
-options are:
-	TRACE		- 0
-	DEBUG		- 1
-	INFO 		- 2
-	WARN		- 3
-	ERROR		- 4
-	CRITICAL	- 5
-	FATAL		- 6
-The default state without updates is: INFO
- */
-FOUNDATION_EXPORT BOOL BindingsLogLevel(long level, NSError* _Nullable* _Nullable error);
-
-/**
- * Login will load an existing client from the storageDir
-using the password. This will fail if the client doesn't exist or
-the password is incorrect.
-The password is passed as a byte array so that it can be cleared from
-memory and stored as securely as possible using the memguard library.
-Login does not block on network connection, and instead loads and
-starts subprocesses to perform network operations.
- */
-FOUNDATION_EXPORT BindingsClient* _Nullable BindingsLogin(NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * MakeIdList creates a new empty IdList.
- */
-FOUNDATION_EXPORT BindingsIdList* _Nullable BindingsMakeIdList(void);
-
-FOUNDATION_EXPORT BindingsIntList* _Nullable BindingsMakeIntList(void);
-
-/**
- * NewClient creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewClient(NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSString* _Nullable regCode, NSError* _Nullable* _Nullable error);
-
-/**
- * NewClientFromBackup constructs a new Client from an encrypted backup. The backup
-is decrypted using the backupPassphrase. On success a successful client creation,
-the function will return a JSON encoded list of the E2E partners
-contained in the backup and a json-encoded string of the parameters stored in the backup
- */
-FOUNDATION_EXPORT NSData* _Nullable BindingsNewClientFromBackup(NSString* _Nullable ndfJSON, NSString* _Nullable storageDir, NSData* _Nullable sessionPassword, NSData* _Nullable backupPassphrase, NSData* _Nullable backupFileContents, NSError* _Nullable* _Nullable error);
-
-/**
- * NewDummyTrafficManager creates a DummyTraffic manager and initialises the
-dummy traffic send thread. Note that the manager does not start sending dummy
-traffic until its status is set to true using DummyTraffic.SetStatus.
-The maxNumMessages is the upper bound of the random number of messages sent
-each send. avgSendDeltaMS is the average duration, in milliseconds, to wait
-between sends. Sends occur every avgSendDeltaMS +/- a random duration with an
-upper bound of randomRangeMS.
- */
-FOUNDATION_EXPORT BindingsDummyTraffic* _Nullable BindingsNewDummyTrafficManager(BindingsClient* _Nullable client, long maxNumMessages, long avgSendDeltaMS, long randomRangeMS, NSError* _Nullable* _Nullable error);
-
-/**
- *  fact object
-creates a new fact. The factType must be either:
- 0 - Username
- 1 - Email
- 2 - Phone Number
-The fact must be well formed for the type and must not include commas or
-semicolons. If it is not well formed, it will be rejected.  Phone numbers
-must have the two letter country codes appended.  For the complete set of
-validation, see /elixxir/primitives/fact/fact.go
- */
-FOUNDATION_EXPORT BindingsFact* _Nullable BindingsNewFact(long factType, NSString* _Nullable factStr, NSError* _Nullable* _Nullable error);
-
-/**
- * FactList
- */
-FOUNDATION_EXPORT BindingsFactList* _Nullable BindingsNewFactList(void);
-
-/**
- * NewFileTransferManager creates a new file transfer manager and starts the
-sending and receiving threads. The receiveFunc is called everytime a new file
-transfer is received.
-The parameters string contains file transfer network configuration options
-and is a JSON formatted string of the fileTransfer.Params object. If it is
-left empty, then defaults are used. It is highly recommended that defaults
-are used. If it is set, it must match the following format:
- {"MaxThroughput":150000,"SendTimeout":500000000}
-MaxThroughput is in bytes/sec and SendTimeout is in nanoseconds.
- */
-FOUNDATION_EXPORT BindingsFileTransfer* _Nullable BindingsNewFileTransferManager(BindingsClient* _Nullable client, id<BindingsFileTransferReceiveFunc> _Nullable receiveFunc, NSString* _Nullable parameters, NSError* _Nullable* _Nullable error);
-
-/**
- * NewGroupManager creates a new group chat manager.
- */
-FOUNDATION_EXPORT BindingsGroupChat* _Nullable BindingsNewGroupManager(BindingsClient* _Nullable client, id<BindingsGroupRequestFunc> _Nullable requestFunc, id<BindingsGroupReceiveFunc> _Nullable receiveFunc, NSError* _Nullable* _Nullable error);
-
-/**
- * NewPrecannedClient creates an insecure user with predetermined keys with nodes
-It creates client storage, generates keys, connects, and registers
-with the network. Note that this does not register a username/identity, but
-merely creates a new cryptographic identity for adding such information
-at a later date.
-
-Users of this function should delete the storage directory on error.
- */
-FOUNDATION_EXPORT BOOL BindingsNewPrecannedClient(long precannedID, NSString* _Nullable network, NSString* _Nullable storageDir, NSData* _Nullable password, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscovery returns a new user discovery object. Only call this once. It must be called
-after StartNetworkFollower is called and will fail if the network has never
-been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscovery(BindingsClient* _Nullable client, NSError* _Nullable* _Nullable error);
-
-/**
- * NewUserDiscoveryFromBackup returns a new user discovery object. It
-wil set up the manager with the backup data. Pass into it the backed up
-facts, one email and phone number each. This will add the registered facts
-to the backed Store. Any one of these fields may be empty,
-however both fields being empty will cause an error. Any other fact that is not
-an email or phone number will return an error. You may only add a fact for the
-accepted types once each. If you attempt to back up a fact type that has already
-been backed up, an error will be returned. Anytime an error is returned, it means
-the backup was not successful.
-NOTE: Do not use this as a direct store operation. This feature is intended to add facts
-to a backend store that have ALREADY BEEN REGISTERED on the account.
-THIS IS NOT FOR ADDING NEWLY REGISTERED FACTS. That is handled on the backend.
-Only call this once. It must be called after StartNetworkFollower
-is called and will fail if the network has never been contacted.
-This function technically has a memory leak because it causes both sides of
-the bindings to think the other is in charge of the client object.
-In general this is not an issue because the client object should exist
-for the life of the program.
-This must be called while start network follower is running.
- */
-FOUNDATION_EXPORT BindingsUserDiscovery* _Nullable BindingsNewUserDiscoveryFromBackup(BindingsClient* _Nullable client, NSString* _Nullable email, NSString* _Nullable phone, NSError* _Nullable* _Nullable error);
-
-/**
- * NotificationsForMe Check if a notification received is for me
-It returns a NotificationForMeReport which contains a ForMe bool stating if it is for the caller,
-a Type, and a source. These are as follows:
-	TYPE       	SOURCE				DESCRIPTION
-	"default"	recipient user ID	A message with no association
-	"request"	sender user ID		A channel request has been received
-	"reset"	    sender user ID		A channel reset has been received
-	"confirm"	sender user ID		A channel request has been accepted
-	"silent"	sender user ID		A message which should not be notified on
-	"e2e"		sender user ID		reception of an E2E message
-	"group"		group ID			reception of a group chat message
- "endFT"     sender user ID		Last message sent confirming end of file transfer
- "groupRQ"   sender user ID		Request from sender to join a group chat
- */
-FOUNDATION_EXPORT BindingsManyNotificationForMeReport* _Nullable BindingsNotificationsForMe(NSString* _Nullable notifCSV, NSString* _Nullable preimages, NSError* _Nullable* _Nullable error);
-
-/**
- * RegisterLogWriter registers a callback on which logs are written.
- */
-FOUNDATION_EXPORT void BindingsRegisterLogWriter(id<BindingsLogWriter> _Nullable writer);
-
-/**
- * RestoreContactsFromBackup takes as input the jason output of the
-`NewClientFromBackup` function, unmarshals it into IDs, looks up
-each ID in user discovery, and initiates a session reset request.
-This function will not return until every id in the list has been sent a
-request. It should be called again and again until it completes.
-xxDK users should not use this function. This function is used by
-the mobile phone apps and are not intended to be part of the xxDK. It
-should be treated as internal functions specific to the phone apps.
- */
-FOUNDATION_EXPORT BindingsRestoreContactsReport* _Nullable BindingsRestoreContactsFromBackup(NSData* _Nullable backupPartnerIDs, BindingsClient* _Nullable client, BindingsUserDiscovery* _Nullable udManager, id<BindingsLookupCallback> _Nullable lookupCB, id<BindingsRestoreContactsUpdater> _Nullable updatesCb);
-
-/**
- * ResumeBackup starts the backup processes back up with a new callback after it
-has been initialized.
-Call this function only when resuming a backup that has already been
-initialized or to replace the callback.
-To start the backup for the first time or to use a new password, use
-InitializeBackup.
- */
-FOUNDATION_EXPORT BindingsBackup* _Nullable BindingsResumeBackup(id<BindingsUpdateBackupFunc> _Nullable cb, BindingsClient* _Nullable c, NSError* _Nullable* _Nullable error);
-
-/**
- * SetTimeSource sets the network time to a custom source.
- */
-FOUNDATION_EXPORT void BindingsSetTimeSource(id<BindingsTimeSource> _Nullable timeNow);
-
-/**
- * StoreSecretWithMnemonic stores the secret tied with the mnemonic to storage.
-Unlike other storage operations, this does not use EKV, as that is
-intrinsically tied to client operations, which the user will not have while
-trying to recover their account. As such, we store the encrypted data
-directly, with a specified path. Path will be a valid filepath in which the
-recover file will be stored as ".recovery".
-
-As an example, given "home/user/xxmessenger/storagePath",
-the recovery file will be stored at
-"home/user/xxmessenger/storagePath/.recovery"
- */
-FOUNDATION_EXPORT NSString* _Nonnull BindingsStoreSecretWithMnemonic(NSData* _Nullable secret, NSString* _Nullable path, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled contact object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsContact* _Nullable BindingsUnmarshalContact(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * Unmarshals a marshaled send report object, returns an error if it fails
- */
-FOUNDATION_EXPORT BindingsSendReport* _Nullable BindingsUnmarshalSendReport(NSData* _Nullable b, NSError* _Nullable* _Nullable error);
-
-/**
- * UpdateCommonErrors takes the passed in contents of a JSON file and updates the
-errToUserErr map with the contents of the json file. The JSON's expected format
-conform with the commented examples provides in errToUserErr above.
-NOTE that you should not pass in a file path, but a preloaded JSON file
- */
-FOUNDATION_EXPORT BOOL BindingsUpdateCommonErrors(NSString* _Nullable jsonFile, NSError* _Nullable* _Nullable error);
-
-// skipped function WrapAPIClient with unsupported parameter or return types
-
-
-// skipped function WrapUserDiscovery with unsupported parameter or return types
-
-
-@class BindingsAuthConfirmCallback;
-
-@class BindingsAuthRequestCallback;
-
-@class BindingsAuthResetNotificationCallback;
-
-@class BindingsClientError;
-
-@class BindingsEventCallbackFunctionObject;
-
-@class BindingsFileTransferReceiveFunc;
-
-@class BindingsFileTransferReceivedProgressFunc;
-
-@class BindingsFileTransferSentProgressFunc;
-
-@class BindingsGroupReceiveFunc;
-
-@class BindingsGroupRequestFunc;
-
-@class BindingsListener;
-
-@class BindingsLogWriter;
-
-@class BindingsLookupCallback;
-
-@class BindingsMessageDeliveryCallback;
-
-@class BindingsMultiLookupCallback;
-
-@class BindingsNetworkHealthCallback;
-
-@class BindingsPreimageNotification;
-
-@class BindingsRestoreContactsUpdater;
-
-@class BindingsRoundCompletionCallback;
-
-@class BindingsRoundEventCallback;
-
-@class BindingsSearchCallback;
-
-@class BindingsSingleSearchCallback;
-
-@class BindingsTimeSource;
-
-@class BindingsUpdateBackupFunc;
-
-/**
- * AuthConfirmCallback notifies the register whenever they receive an auth
-request confirmation
- */
-@interface BindingsAuthConfirmCallback : NSObject <goSeqRefInterface, BindingsAuthConfirmCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)partner;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthRequestCallback : NSObject <goSeqRefInterface, BindingsAuthRequestCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-/**
- * AuthRequestCallback notifies the register whenever they receive an auth
-request
- */
-@interface BindingsAuthResetNotificationCallback : NSObject <goSeqRefInterface, BindingsAuthResetNotificationCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)requestor;
-@end
-
-@interface BindingsClientError : NSObject <goSeqRefInterface, BindingsClientError> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)report:(NSString* _Nullable)source message:(NSString* _Nullable)message trace:(NSString* _Nullable)trace;
-@end
-
-/**
- * EventCallbackFunctionObject bindings interface which contains function
-that implements the EventCallbackFunction
- */
-@interface BindingsEventCallbackFunctionObject : NSObject <goSeqRefInterface, BindingsEventCallbackFunctionObject> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)reportEvent:(long)priority category:(NSString* _Nullable)category evtType:(NSString* _Nullable)evtType details:(NSString* _Nullable)details;
-@end
-
-/**
- * FileTransferReceiveFunc contains a function callback that notifies the
-receiver of an incoming file transfer. It is called on the reception of the
-initial file transfer message.
- */
-@interface BindingsFileTransferReceiveFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receiveCallback:(NSData* _Nullable)tid fileName:(NSString* _Nullable)fileName fileType:(NSString* _Nullable)fileType sender:(NSData* _Nullable)sender size:(long)size preview:(NSData* _Nullable)preview;
-@end
-
-/**
- * FileTransferReceivedProgressFunc contains a function callback that tracks the
-progress of receiving a file. It is called when a file part is received, the
-transfer completes, or on error.
- */
-@interface BindingsFileTransferReceivedProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferReceivedProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)receivedProgressCallback:(BOOL)completed received:(long)received total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * FileTransferSentProgressFunc contains a function callback that tracks the
-progress of sending a file. It is called when a file part is sent, a file
-part arrives, the transfer completes, or on error.
- */
-@interface BindingsFileTransferSentProgressFunc : NSObject <goSeqRefInterface, BindingsFileTransferSentProgressFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)sentProgressCallback:(BOOL)completed sent:(long)sent arrived:(long)arrived total:(long)total t:(BindingsFilePartTracker* _Nullable)t err:(NSError* _Nullable)err;
-@end
-
-/**
- * GroupReceiveFunc contains a function callback that is called when a group
-message is received.
- */
-@interface BindingsGroupReceiveFunc : NSObject <goSeqRefInterface, BindingsGroupReceiveFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupReceiveCallback:(BindingsGroupMessageReceive* _Nullable)msg;
-@end
-
-/**
- * GroupRequestFunc contains a function callback that is called when a group
-request is received.
- */
-@interface BindingsGroupRequestFunc : NSObject <goSeqRefInterface, BindingsGroupRequestFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)groupRequestCallback:(BindingsGroup* _Nullable)g;
-@end
-
-/**
- * Listener provides a callback to hear a message
-An object implementing this interface can be called back when the client
-gets a message of the type that the registerer specified at registration
-time.
- */
-@interface BindingsListener : NSObject <goSeqRefInterface, BindingsListener> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * Hear is called to receive a message in the UI
- */
-- (void)hear:(BindingsMessage* _Nullable)message;
-/**
- * Returns a name, used for debugging
- */
-- (NSString* _Nonnull)name;
-@end
-
-@interface BindingsLogWriter : NSObject <goSeqRefInterface, BindingsLogWriter> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)log:(NSString* _Nullable)p0;
-@end
-
-/**
- * LookupCallback returns the result of a single lookup
- */
-@interface BindingsLookupCallback : NSObject <goSeqRefInterface, BindingsLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-/**
- * MessageDeliveryCallback gets called on the determination if all events
-related to a message send were successful.
- */
-@interface BindingsMessageDeliveryCallback : NSObject <goSeqRefInterface, BindingsMessageDeliveryCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(NSData* _Nullable)msgID delivered:(BOOL)delivered timedOut:(BOOL)timedOut roundResults:(NSData* _Nullable)roundResults;
-@end
-
-/**
- * MultiLookupCallback returns the result of many parallel lookups
- */
-@interface BindingsMultiLookupCallback : NSObject <goSeqRefInterface, BindingsMultiLookupCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)Succeeded failed:(BindingsIdList* _Nullable)failed errors:(NSString* _Nullable)errors;
-@end
-
-/**
- * A callback when which is used to receive notification if network health
-changes
- */
-@interface BindingsNetworkHealthCallback : NSObject <goSeqRefInterface, BindingsNetworkHealthCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BOOL)p0;
-@end
-
-@interface BindingsPreimageNotification : NSObject <goSeqRefInterface, BindingsPreimageNotification> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)notify:(NSData* _Nullable)identity deleted:(BOOL)deleted;
-@end
-
-/**
- * RestoreContactsUpdater interface provides a callback function
-for receiving update information from RestoreContactsFromBackup.
- */
-@interface BindingsRestoreContactsUpdater : NSObject <goSeqRefInterface, BindingsRestoreContactsUpdater> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-/**
- * RestoreContactsCallback is called to report the current # of contacts
-that have been found and how many have been restored
-against the total number that need to be
-processed. If an error occurs it it set on the err variable as a
-plain string.
- */
-- (void)restoreContactsCallback:(long)numFound numRestored:(long)numRestored total:(long)total err:(NSString* _Nullable)err;
-@end
-
-/**
- * RoundCompletionCallback is returned when the completion of a round is known.
- */
-@interface BindingsRoundCompletionCallback : NSObject <goSeqRefInterface, BindingsRoundCompletionCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid success:(BOOL)success timedOut:(BOOL)timedOut;
-@end
-
-/**
- * RoundEventCallback handles waiting on the exact state of a round on
-the cMix network.
- */
-@interface BindingsRoundEventCallback : NSObject <goSeqRefInterface, BindingsRoundEventCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)eventCallback:(long)rid state:(long)state timedOut:(BOOL)timedOut;
-@end
-
-/**
- * SearchCallback returns the result of a search
- */
-@interface BindingsSearchCallback : NSObject <goSeqRefInterface, BindingsSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContactList* _Nullable)contacts error:(NSString* _Nullable)error;
-@end
-
-/**
- * SingleSearchCallback returns the result of a single search
- */
-@interface BindingsSingleSearchCallback : NSObject <goSeqRefInterface, BindingsSingleSearchCallback> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)callback:(BindingsContact* _Nullable)contact error:(NSString* _Nullable)error;
-@end
-
-@interface BindingsTimeSource : NSObject <goSeqRefInterface, BindingsTimeSource> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (int64_t)nowMs;
-@end
-
-/**
- * UpdateBackupFunc contains a function callback that returns new backups.
- */
-@interface BindingsUpdateBackupFunc : NSObject <goSeqRefInterface, BindingsUpdateBackupFunc> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (void)updateBackup:(NSData* _Nullable)encryptedBackup;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Universe.objc.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Universe.objc.h
deleted file mode 100644
index 019e7502d581983722a15bf30799e85cbc5dd766..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/Universe.objc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Objective-C API for talking to  Go package.
-//   gobind -lang=objc 
-//
-// File is generated by gobind. Do not edit.
-
-#ifndef __Universe_H__
-#define __Universe_H__
-
-@import Foundation;
-#include "ref.h"
-
-@protocol Universeerror;
-@class Universeerror;
-
-@protocol Universeerror <NSObject>
-- (NSString* _Nonnull)error;
-@end
-
-@class Universeerror;
-
-@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
-}
-@property(strong, readonly) _Nonnull id _ref;
-
-- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
-- (NSString* _Nonnull)error;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/ref.h b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/ref.h
deleted file mode 100644
index b8036a4d85c7387f3def61473a071b5d8c4c8208..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Headers/ref.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-#ifndef __GO_REF_HDR__
-#define __GO_REF_HDR__
-
-#include <Foundation/Foundation.h>
-
-// GoSeqRef is an object tagged with an integer for passing back and
-// forth across the language boundary. A GoSeqRef may represent either
-// an instance of a Go object, or an Objective-C object passed to Go.
-// The explicit allocation of a GoSeqRef is used to pin a Go object
-// when it is passed to Objective-C. The Go seq package maintains a
-// reference to the Go object in a map keyed by the refnum along with
-// a reference count. When the reference count reaches zero, the Go
-// seq package will clear the corresponding entry in the map.
-@interface GoSeqRef : NSObject {
-}
-@property(readonly) int32_t refnum;
-@property(strong) id obj; // NULL when representing a Go object.
-
-// new GoSeqRef object to proxy a Go object. The refnum must be
-// provided from Go side.
-- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
-
-- (int32_t)incNum;
-
-@end
-
-@protocol goSeqRefInterface
--(GoSeqRef*) _ref;
-@end
-
-#endif
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Modules/module.modulemap b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Modules/module.modulemap
deleted file mode 100644
index 4316a5b24058edfc18ffb2dc7f7a982e8353441a..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Modules/module.modulemap
+++ /dev/null
@@ -1,8 +0,0 @@
-framework module "Bindings" {
-	header "ref.h"
-    header "Bindings.objc.h"
-    header "Universe.objc.h"
-    header "Bindings.h"
-
-    export *
-}
\ No newline at end of file
diff --git a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Resources/Info.plist b/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Resources/Info.plist
deleted file mode 100644
index 0d1a4b8ab9b1fc8e9357197398f73353470cb636..0000000000000000000000000000000000000000
--- a/XCFrameworks/Bindings.xcframework/ios-arm64_x86_64-simulator/Bindings.framework/Versions/Current/Resources/Info.plist
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-    <plist version="1.0">
-      <dict>
-      </dict>
-    </plist>
diff --git a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
index fa732be43c432b37cc0f8bd9f88a1e9c9d2f4592..a54280f2babcb8bf2fd3df02e19585ae88ae4eb1 100644
--- a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -386,15 +386,6 @@
         "revision" : "16e6409ee82e1b81390bdffbf217b9c08ab32784",
         "version" : "0.5.0"
       }
-    },
-    {
-      "identity" : "xxm-di",
-      "kind" : "remoteSourceControl",
-      "location" : "https://git.xx.network/elixxir/xxm-di",
-      "state" : {
-        "revision" : "43b1e12c32109f1753fcc62e5b0b21e479ee27e3",
-        "version" : "1.0.0"
-      }
     }
   ],
   "version" : 2
diff --git a/run_swiftgen.sh b/run_swiftgen.sh
index 63ba2cb744a4016ea02e72cff976714ccc44f1dc..adfb40051d165d4ae1211553b486d776c6e4bd49 100755
--- a/run_swiftgen.sh
+++ b/run_swiftgen.sh
@@ -1,2 +1,2 @@
 #!/bin/bash
-swiftgen config run --config Sources/Shared/swiftgen.yml
+swiftgen config run --config Sources/AppResources/swiftgen.yml