diff --git a/Examples/xx-messenger/.swiftpm/xcode/xcshareddata/xcschemes/ContactLookupFeature.xcscheme b/Examples/xx-messenger/.swiftpm/xcode/xcshareddata/xcschemes/ContactLookupFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..e0070c64629dce6e785c4bb8590d0b330d522f5b
--- /dev/null
+++ b/Examples/xx-messenger/.swiftpm/xcode/xcshareddata/xcschemes/ContactLookupFeature.xcscheme
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1400"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "ContactLookupFeature"
+               BuildableName = "ContactLookupFeature"
+               BlueprintName = "ContactLookupFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      codeCoverageEnabled = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "ContactLookupFeatureTests"
+               BuildableName = "ContactLookupFeatureTests"
+               BlueprintName = "ContactLookupFeatureTests"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </TestableReference>
+      </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 = "ContactLookupFeature"
+            BuildableName = "ContactLookupFeature"
+            BlueprintName = "ContactLookupFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index 4668d629ddf3b295ce57fe54329d28101e94c7ff..d863e016e9f28069ddcc36104793639aef96be33 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -20,6 +20,7 @@ let package = Package(
     .library(name: "CheckContactAuthFeature", targets: ["CheckContactAuthFeature"]),
     .library(name: "ConfirmRequestFeature", targets: ["ConfirmRequestFeature"]),
     .library(name: "ContactFeature", targets: ["ContactFeature"]),
+    .library(name: "ContactLookupFeature", targets: ["ContactLookupFeature"]),
     .library(name: "ContactsFeature", targets: ["ContactsFeature"]),
     .library(name: "HomeFeature", targets: ["HomeFeature"]),
     .library(name: "MyContactFeature", targets: ["MyContactFeature"]),
@@ -89,6 +90,7 @@ let package = Package(
         .target(name: "CheckContactAuthFeature"),
         .target(name: "ConfirmRequestFeature"),
         .target(name: "ContactFeature"),
+        .target(name: "ContactLookupFeature"),
         .target(name: "ContactsFeature"),
         .target(name: "HomeFeature"),
         .target(name: "MyContactFeature"),
@@ -117,10 +119,8 @@ let package = Package(
     .target(
       name: "BackupFeature",
       dependencies: [
-        .target(name: "AppCore"),
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
-        .product(name: "XXModels", package: "client-ios-db"),
       ],
       swiftSettings: swiftSettings
     ),
@@ -191,6 +191,7 @@ let package = Package(
         .target(name: "ChatFeature"),
         .target(name: "CheckContactAuthFeature"),
         .target(name: "ConfirmRequestFeature"),
+        .target(name: "ContactLookupFeature"),
         .target(name: "SendRequestFeature"),
         .target(name: "VerifyContactFeature"),
         .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
@@ -208,6 +209,24 @@ let package = Package(
       ],
       swiftSettings: swiftSettings
     ),
+    .target(
+      name: "ContactLookupFeature",
+      dependencies: [
+        .target(name: "AppCore"),
+        .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
+        .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
+        .product(name: "XXModels", package: "client-ios-db"),
+      ],
+      swiftSettings: swiftSettings
+    ),
+    .testTarget(
+      name: "ContactLookupFeatureTests",
+      dependencies: [
+        .target(name: "ContactLookupFeature"),
+        .product(name: "CustomDump", package: "swift-custom-dump"),
+      ],
+      swiftSettings: swiftSettings
+    ),
     .target(
       name: "ContactsFeature",
       dependencies: [
diff --git a/Examples/xx-messenger/Project/XXMessenger.xcodeproj/xcshareddata/xcschemes/XXMessenger.xcscheme b/Examples/xx-messenger/Project/XXMessenger.xcodeproj/xcshareddata/xcschemes/XXMessenger.xcscheme
index b50f1c107c6e3f6e79c5c4c22e64b4368732de84..42a3cede69290ef2541f14fb20a7c54ad71831b5 100644
--- a/Examples/xx-messenger/Project/XXMessenger.xcodeproj/xcshareddata/xcschemes/XXMessenger.xcscheme
+++ b/Examples/xx-messenger/Project/XXMessenger.xcodeproj/xcshareddata/xcschemes/XXMessenger.xcscheme
@@ -99,6 +99,16 @@
                ReferencedContainer = "container:..">
             </BuildableReference>
          </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "ContactLookupFeatureTests"
+               BuildableName = "ContactLookupFeatureTests"
+               BlueprintName = "ContactLookupFeatureTests"
+               ReferencedContainer = "container:..">
+            </BuildableReference>
+         </TestableReference>
          <TestableReference
             skipped = "NO">
             <BuildableReference
diff --git a/Examples/xx-messenger/Sources/AppCore/SharedUI/Data+hexString.swift b/Examples/xx-messenger/Sources/AppCore/SharedUI/Data+hexString.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e8010b95c6fbeea66049228f1129f929559bdf86
--- /dev/null
+++ b/Examples/xx-messenger/Sources/AppCore/SharedUI/Data+hexString.swift
@@ -0,0 +1,7 @@
+import Foundation
+
+extension Data {
+  public func hexString(bytesSeparator: String = " ") -> String {
+    map { String(format: "%02hhx\(bytesSeparator)", $0) }.joined()
+  }
+}
diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index 3cf2cb0b065eda90aeff16cf1ce76f14297fd012..ce52387f7624f3d3583f0be4e95571926327b754 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -4,6 +4,7 @@ import ChatFeature
 import CheckContactAuthFeature
 import ConfirmRequestFeature
 import ContactFeature
+import ContactLookupFeature
 import ContactsFeature
 import Foundation
 import HomeFeature
@@ -37,6 +38,13 @@ extension AppEnvironment {
       db: dbManager.getDB,
       mainQueue: mainQueue,
       bgQueue: bgQueue,
+      lookup: {
+        ContactLookupEnvironment(
+          messenger: messenger,
+          mainQueue: mainQueue,
+          bgQueue: bgQueue
+        )
+      },
       sendRequest: {
         SendRequestEnvironment(
           messenger: messenger,
@@ -156,7 +164,6 @@ extension AppEnvironment {
           backup: {
             BackupEnvironment(
               messenger: messenger,
-              db: dbManager.getDB,
               backupStorage: backupStorage,
               mainQueue: mainQueue,
               bgQueue: bgQueue
diff --git a/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift b/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift
index f672b312a1867790a10ffb54f84cd683084a1b22..8010f17d1d0727c4621841dd124a93dcda0e0b5d 100644
--- a/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift
+++ b/Examples/xx-messenger/Sources/BackupFeature/BackupFeature.swift
@@ -1,15 +1,16 @@
-import AppCore
 import Combine
 import ComposableArchitecture
 import Foundation
 import XXClient
 import XXMessengerClient
-import XXModels
 
 public struct BackupState: Equatable {
+  public enum Field: String, Hashable {
+    case passphrase
+  }
+
   public enum Error: String, Swift.Error, Equatable {
-    case dbContactNotFound
-    case dbContactUsernameMissing
+    case contactUsernameMissing
   }
 
   public init(
@@ -19,6 +20,7 @@ public struct BackupState: Equatable {
     isStopping: Bool = false,
     backup: BackupStorage.Backup? = nil,
     alert: AlertState<BackupAction>? = nil,
+    focusedField: Field? = nil,
     passphrase: String = "",
     isExporting: Bool = false,
     exportData: Data? = nil
@@ -29,6 +31,7 @@ public struct BackupState: Equatable {
     self.isStopping = isStopping
     self.backup = backup
     self.alert = alert
+    self.focusedField = focusedField
     self.passphrase = passphrase
     self.isExporting = isExporting
     self.exportData = exportData
@@ -40,6 +43,7 @@ public struct BackupState: Equatable {
   public var isStopping: Bool
   public var backup: BackupStorage.Backup?
   public var alert: AlertState<BackupAction>?
+  @BindableState public var focusedField: Field?
   @BindableState public var passphrase: String
   @BindableState public var isExporting: Bool
   public var exportData: Data?
@@ -64,20 +68,17 @@ public enum BackupAction: Equatable, BindableAction {
 public struct BackupEnvironment {
   public init(
     messenger: Messenger,
-    db: DBManagerGetDB,
     backupStorage: BackupStorage,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>
   ) {
     self.messenger = messenger
-    self.db = db
     self.backupStorage = backupStorage
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
   }
 
   public var messenger: Messenger
-  public var db: DBManagerGetDB
   public var backupStorage: BackupStorage
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
@@ -87,7 +88,6 @@ public struct BackupEnvironment {
 extension BackupEnvironment {
   public static let unimplemented = BackupEnvironment(
     messenger: .unimplemented,
-    db: .unimplemented,
     backupStorage: .unimplemented,
     mainQueue: .unimplemented,
     bgQueue: .unimplemented
@@ -119,17 +119,12 @@ public let backupReducer = Reducer<BackupState, BackupAction, BackupEnvironment>
 
   case .startTapped:
     state.isStarting = true
+    state.focusedField = nil
     return Effect.run { [state] subscriber in
       do {
-        let e2e: E2E = try env.messenger.e2e.tryGet()
-        let contactID = try e2e.getContact().getId()
-        let db = try env.db()
-        let query = XXModels.Contact.Query(id: [contactID])
-        guard let contact = try db.fetchContacts(query).first else {
-          throw BackupState.Error.dbContactNotFound
-        }
-        guard let username = contact.username else {
-          throw BackupState.Error.dbContactUsernameMissing
+        let contact = try env.messenger.myContact(includeFacts: .types([.username]))
+        guard let username = try contact.getFact(.username)?.value else {
+          throw BackupState.Error.contactUsernameMissing
         }
         try env.messenger.startBackup(
           password: state.passphrase,
diff --git a/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift b/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
index 54fc6567cd07eac6c5649fa5a35e6b28a91fe3eb..89510b2fbf2c993afa1438fd62408dc925d1c30e 100644
--- a/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
+++ b/Examples/xx-messenger/Sources/BackupFeature/BackupView.swift
@@ -8,6 +8,7 @@ public struct BackupView: View {
   }
 
   let store: Store<BackupState, BackupAction>
+  @FocusState var focusedField: BackupState.Field?
 
   struct ViewState: Equatable {
     struct Backup: Equatable {
@@ -23,6 +24,7 @@ public struct BackupView: View {
       backup = state.backup.map { backup in
         Backup(date: backup.date, size: backup.data.count)
       }
+      focusedField = state.focusedField
       passphrase = state.passphrase
       isExporting = state.isExporting
       exportData = state.exportData
@@ -34,6 +36,7 @@ public struct BackupView: View {
     var isStopping: Bool
     var isLoading: Bool { isStarting || isResuming || isStopping }
     var backup: Backup?
+    var focusedField: BackupState.Field?
     var passphrase: String
     var isExporting: Bool
     var exportData: Data?
@@ -57,9 +60,9 @@ public struct BackupView: View {
         )
       }
       .navigationTitle("Backup")
-      .task {
-        await viewStore.send(.task).finish()
-      }
+      .task { await viewStore.send(.task).finish() }
+      .onChange(of: viewStore.focusedField) { focusedField = $0 }
+      .onChange(of: focusedField) { viewStore.send(.set(\.$focusedField, $0)) }
     }
   }
 
@@ -75,6 +78,11 @@ public struct BackupView: View {
         prompt: Text("Backup passphrase"),
         label: { Text("Backup passphrase") }
       )
+      .textContentType(.password)
+      .textInputAutocapitalization(.never)
+      .disableAutocorrection(true)
+      .focused($focusedField, equals: .passphrase)
+
       Button {
         viewStore.send(.startTapped)
       } label: {
@@ -91,6 +99,7 @@ public struct BackupView: View {
     } header: {
       Text("New backup")
     }
+    .disabled(viewStore.isStarting)
   }
 
   @ViewBuilder func backupSection(
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
index 993796e4bf4f286a29fdb7319fb39332074c68da..dc166e4ee49bf7d36d410caeb16589cf88be0439 100644
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactFeature.swift
@@ -4,6 +4,7 @@ import CheckContactAuthFeature
 import ComposableArchitecture
 import ComposablePresentation
 import ConfirmRequestFeature
+import ContactLookupFeature
 import Foundation
 import SendRequestFeature
 import VerifyContactFeature
@@ -20,6 +21,7 @@ public struct ContactState: Equatable {
     importUsername: Bool = true,
     importEmail: Bool = true,
     importPhone: Bool = true,
+    lookup: ContactLookupState? = nil,
     sendRequest: SendRequestState? = nil,
     verifyContact: VerifyContactState? = nil,
     confirmRequest: ConfirmRequestState? = nil,
@@ -32,6 +34,7 @@ public struct ContactState: Equatable {
     self.importUsername = importUsername
     self.importEmail = importEmail
     self.importPhone = importPhone
+    self.lookup = lookup
     self.sendRequest = sendRequest
     self.verifyContact = verifyContact
     self.confirmRequest = confirmRequest
@@ -45,6 +48,7 @@ public struct ContactState: Equatable {
   @BindableState public var importUsername: Bool
   @BindableState public var importEmail: Bool
   @BindableState public var importPhone: Bool
+  public var lookup: ContactLookupState?
   public var sendRequest: SendRequestState?
   public var verifyContact: VerifyContactState?
   public var confirmRequest: ConfirmRequestState?
@@ -56,6 +60,9 @@ public enum ContactAction: Equatable, BindableAction {
   case start
   case dbContactFetched(XXModels.Contact?)
   case importFactsTapped
+  case lookupTapped
+  case lookupDismissed
+  case lookup(ContactLookupAction)
   case sendRequestTapped
   case sendRequestDismissed
   case sendRequest(SendRequestAction)
@@ -80,6 +87,7 @@ public struct ContactEnvironment {
     db: DBManagerGetDB,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>,
+    lookup: @escaping () -> ContactLookupEnvironment,
     sendRequest: @escaping () -> SendRequestEnvironment,
     verifyContact: @escaping () -> VerifyContactEnvironment,
     confirmRequest: @escaping () -> ConfirmRequestEnvironment,
@@ -90,6 +98,7 @@ public struct ContactEnvironment {
     self.db = db
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
+    self.lookup = lookup
     self.sendRequest = sendRequest
     self.verifyContact = verifyContact
     self.confirmRequest = confirmRequest
@@ -101,6 +110,7 @@ public struct ContactEnvironment {
   public var db: DBManagerGetDB
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
+  public var lookup: () -> ContactLookupEnvironment
   public var sendRequest: () -> SendRequestEnvironment
   public var verifyContact: () -> VerifyContactEnvironment
   public var confirmRequest: () -> ConfirmRequestEnvironment
@@ -115,6 +125,7 @@ extension ContactEnvironment {
     db: .unimplemented,
     mainQueue: .unimplemented,
     bgQueue: .unimplemented,
+    lookup: { .unimplemented },
     sendRequest: { .unimplemented },
     verifyContact: { .unimplemented },
     confirmRequest: { .unimplemented },
@@ -163,6 +174,19 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
     .receive(on: env.mainQueue)
     .eraseToEffect()
 
+  case .lookupTapped:
+    state.lookup = ContactLookupState(id: state.id)
+    return .none
+
+  case .lookupDismissed:
+    state.lookup = nil
+    return .none
+
+  case .lookup(.didLookup(let xxContact)):
+    state.xxContact = xxContact
+    state.lookup = nil
+    return .none
+
   case .sendRequestTapped:
     if let xxContact = state.xxContact {
       state.sendRequest = SendRequestState(contact: xxContact)
@@ -223,11 +247,20 @@ public let contactReducer = Reducer<ContactState, ContactAction, ContactEnvironm
     state.chat = nil
     return .none
 
-  case .binding(_), .sendRequest(_), .verifyContact(_), .confirmRequest(_), .checkAuth(_), .chat(_):
+  case .binding(_), .lookup(_), .sendRequest(_),
+      .verifyContact(_), .confirmRequest(_),
+      .checkAuth(_), .chat(_):
     return .none
   }
 }
 .binding()
+.presenting(
+  contactLookupReducer,
+  state: .keyPath(\.lookup),
+  id: .notNil(),
+  action: /ContactAction.lookup,
+  environment: { $0.lookup() }
+)
 .presenting(
   sendRequestReducer,
   state: .keyPath(\.sendRequest),
diff --git a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
index d775df01eeed7ee6175b00d231149a351be84882..daa84903edacd947fb7173c3196e8ea7f5c1cf0d 100644
--- a/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
+++ b/Examples/xx-messenger/Sources/ContactFeature/ContactView.swift
@@ -4,6 +4,7 @@ import CheckContactAuthFeature
 import ComposableArchitecture
 import ComposablePresentation
 import ConfirmRequestFeature
+import ContactLookupFeature
 import SendRequestFeature
 import SwiftUI
 import VerifyContactFeature
@@ -26,6 +27,11 @@ public struct ContactView: View {
     var importUsername: Bool
     var importEmail: Bool
     var importPhone: Bool
+    var canLookup: Bool
+    var canSendRequest: Bool
+    var canVerifyContact: Bool
+    var canConfirmRequest: Bool
+    var canCheckAuthorization: Bool
 
     init(state: ContactState) {
       dbContact = state.dbContact
@@ -36,6 +42,11 @@ public struct ContactView: View {
       importUsername = state.importUsername
       importEmail = state.importEmail
       importPhone = state.importPhone
+      canLookup = state.dbContact?.id != nil
+      canSendRequest = state.xxContact != nil || state.dbContact?.marshaled != nil
+      canVerifyContact = state.dbContact?.marshaled != nil
+      canConfirmRequest = state.dbContact?.marshaled != nil
+      canCheckAuthorization = state.dbContact?.marshaled != nil
     }
   }
 
@@ -100,15 +111,30 @@ public struct ContactView: View {
 
         if let dbContact = viewStore.dbContact {
           Section {
+            Label(dbContact.id.hexString(), systemImage: "number")
+              .font(.footnote.monospaced())
             Label(dbContact.username ?? "", systemImage: "person")
             Label(dbContact.email ?? "", systemImage: "envelope")
             Label(dbContact.phone ?? "", systemImage: "phone")
           } header: {
             Text("Contact")
           }
+          .textSelection(.enabled)
 
           Section {
             ContactAuthStatusView(dbContact.authStatus)
+
+            Button {
+              viewStore.send(.lookupTapped)
+            } label: {
+              HStack {
+                Text("Lookup")
+                Spacer()
+                Image(systemName: "chevron.forward")
+              }
+            }
+            .disabled(!viewStore.canLookup)
+
             Button {
               viewStore.send(.sendRequestTapped)
             } label: {
@@ -118,6 +144,8 @@ public struct ContactView: View {
                 Image(systemName: "chevron.forward")
               }
             }
+            .disabled(!viewStore.canSendRequest)
+
             Button {
               viewStore.send(.verifyContactTapped)
             } label: {
@@ -127,6 +155,8 @@ public struct ContactView: View {
                 Image(systemName: "chevron.forward")
               }
             }
+            .disabled(!viewStore.canVerifyContact)
+
             Button {
               viewStore.send(.confirmRequestTapped)
             } label: {
@@ -136,6 +166,8 @@ public struct ContactView: View {
                 Image(systemName: "chevron.forward")
               }
             }
+            .disabled(!viewStore.canConfirmRequest)
+
             Button {
               viewStore.send(.checkAuthTapped)
             } label: {
@@ -145,6 +177,7 @@ public struct ContactView: View {
                 Image(systemName: "chevron.forward")
               }
             }
+            .disabled(!viewStore.canCheckAuthorization)
           } header: {
             Text("Auth")
           }
@@ -167,6 +200,15 @@ public struct ContactView: View {
       }
       .navigationTitle("Contact")
       .task { viewStore.send(.start) }
+      .background(NavigationLinkWithStore(
+        store.scope(
+          state: \.lookup,
+          action: ContactAction.lookup
+        ),
+        mapState: replayNonNil(),
+        onDeactivate: { viewStore.send(.lookupDismissed) },
+        destination: ContactLookupView.init(store:)
+      ))
       .background(NavigationLinkWithStore(
         store.scope(
           state: \.sendRequest,
diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0b6f92dd46b351f6d10f78ef4b50961dad3e1fae
--- /dev/null
+++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupFeature.swift
@@ -0,0 +1,83 @@
+import ComposableArchitecture
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+
+public struct ContactLookupState: Equatable {
+  public init(
+    id: Data,
+    isLookingUp: Bool = false,
+    failure: String? = nil
+  ) {
+    self.id = id
+    self.isLookingUp = isLookingUp
+    self.failure = failure
+  }
+
+  public var id: Data
+  public var isLookingUp: Bool
+  public var failure: String?
+}
+
+public enum ContactLookupAction: Equatable {
+  case lookupTapped
+  case didLookup(XXClient.Contact)
+  case didFail(NSError)
+}
+
+public struct ContactLookupEnvironment {
+  public init(
+    messenger: Messenger,
+    mainQueue: AnySchedulerOf<DispatchQueue>,
+    bgQueue: AnySchedulerOf<DispatchQueue>
+  ) {
+    self.messenger = messenger
+    self.mainQueue = mainQueue
+    self.bgQueue = bgQueue
+  }
+
+  public var messenger: Messenger
+  public var mainQueue: AnySchedulerOf<DispatchQueue>
+  public var bgQueue: AnySchedulerOf<DispatchQueue>
+}
+
+#if DEBUG
+extension ContactLookupEnvironment {
+  public static let unimplemented = ContactLookupEnvironment(
+    messenger: .unimplemented,
+    mainQueue: .unimplemented,
+    bgQueue: .unimplemented
+  )
+}
+#endif
+
+public let contactLookupReducer = Reducer<ContactLookupState, ContactLookupAction, ContactLookupEnvironment>
+{ state, action, env in
+  switch action {
+  case .lookupTapped:
+    state.isLookingUp = true
+    state.failure = nil
+    return Effect.result { [state] in
+      do {
+        let contact = try env.messenger.lookupContact(id: state.id)
+        return .success(.didLookup(contact))
+      } catch {
+        return .success(.didFail(error as NSError))
+      }
+    }
+    .subscribe(on: env.bgQueue)
+    .receive(on: env.mainQueue)
+    .eraseToEffect()
+
+  case .didLookup(_):
+    state.isLookingUp = false
+    state.failure = nil
+    return .none
+
+  case .didFail(let error):
+    state.isLookingUp = false
+    state.failure = error.localizedDescription
+    return .none
+  }
+}
diff --git a/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6ce83eda6ba5dacfcf15c2fca4e8c202087ef42d
--- /dev/null
+++ b/Examples/xx-messenger/Sources/ContactLookupFeature/ContactLookupView.swift
@@ -0,0 +1,76 @@
+import AppCore
+import ComposableArchitecture
+import SwiftUI
+
+public struct ContactLookupView: View {
+  public init(store: Store<ContactLookupState, ContactLookupAction>) {
+    self.store = store
+  }
+
+  let store: Store<ContactLookupState, ContactLookupAction>
+
+  struct ViewState: Equatable {
+    init(state: ContactLookupState) {
+      id = state.id
+      isLookingUp = state.isLookingUp
+      failure = state.failure
+    }
+
+    var id: Data
+    var isLookingUp: Bool
+    var failure: String?
+  }
+
+  public var body: some View {
+    WithViewStore(store, observe: ViewState.init) { viewStore in
+      Form {
+        Section {
+          Label(viewStore.id.hexString(), systemImage: "number")
+            .font(.footnote.monospaced())
+
+          Button {
+            viewStore.send(.lookupTapped)
+          } label: {
+            HStack {
+              Text("Lookup")
+              Spacer()
+              if viewStore.isLookingUp {
+                ProgressView()
+              } else {
+                Image(systemName: "magnifyingglass")
+              }
+            }
+          }
+          .disabled(viewStore.isLookingUp)
+        } header: {
+          Text("Contact ID")
+        }
+
+        if let failure = viewStore.failure {
+          Section {
+            Text(failure)
+          } header: {
+            Text("Error")
+          }
+        }
+      }
+      .navigationTitle("Lookup")
+    }
+  }
+}
+
+#if DEBUG
+public struct ContactLookupView_Previews: PreviewProvider {
+  public static var previews: some View {
+    NavigationView {
+      ContactLookupView(store: Store(
+        initialState: ContactLookupState(
+          id: "1234".data(using: .utf8)!
+        ),
+        reducer: .empty,
+        environment: ()
+      ))
+    }
+  }
+}
+#endif
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
index b25d021257e34cbc8b23cafa4f4ef1c44815dbff..434a1aca3c7cdc74b340c54a22558fa67a90a0eb 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
@@ -285,6 +285,7 @@ public let myContactReducer = Reducer<MyContactState, MyContactAction, MyContact
         let contactId = try env.messenger.e2e.tryGet().getContact().getId()
         if var dbContact = try env.db().fetchContacts(.init(id: [contactId])).first {
           let facts = try env.messenger.ud.tryGet().getFacts()
+          dbContact.username = facts.get(.username)?.value
           dbContact.email = facts.get(.email)?.value
           dbContact.phone = facts.get(.phone)?.value
           try env.db().saveContact(dbContact)
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
index f32af24270f762b6a11f5a43602f013709e14344..d32a6f68848e89ad7eeb4a9bf5f25b543d379f40 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
@@ -1,3 +1,4 @@
+import AppCore
 import ComposableArchitecture
 import SwiftUI
 import XXModels
@@ -49,8 +50,17 @@ public struct MyContactView: View {
   public var body: some View {
     WithViewStore(store, observe: ViewState.init) { viewStore in
       Form {
+        Section {
+          Text(viewStore.contact?.id.hexString() ?? "")
+            .font(.footnote.monospaced())
+            .textSelection(.enabled)
+        } header: {
+          Label("ID", systemImage: "number")
+        }
+
         Section {
           Text(viewStore.contact?.username ?? "")
+            .textSelection(.enabled)
         } header: {
           Label("Username", systemImage: "person")
         }
@@ -59,6 +69,7 @@ public struct MyContactView: View {
           if let contact = viewStore.contact {
             if let email = contact.email {
               Text(email)
+                .textSelection(.enabled)
               Button(role: .destructive) {
                 viewStore.send(.unregisterEmailTapped)
               } label: {
@@ -135,6 +146,7 @@ public struct MyContactView: View {
           if let contact = viewStore.contact {
             if let phone = contact.phone {
               Text(phone)
+                .textSelection(.enabled)
               Button(role: .destructive) {
                 viewStore.send(.unregisterPhoneTapped)
               } label: {
diff --git a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
index cb43c43056f6d3e53c2b73b4bdfc10189f052b21..9b9754c60eb11b019a7674d6c247698f5b16ef01 100644
--- a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
+++ b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
@@ -7,6 +7,10 @@ import XXMessengerClient
 import XXModels
 
 public struct RegisterState: Equatable {
+  public enum Error: Swift.Error, Equatable {
+    case usernameMismatch(registering: String, registered: String?)
+  }
+
   public enum Field: String, Hashable {
     case username
   }
@@ -82,14 +86,22 @@ public let registerReducer = Reducer<RegisterState, RegisterAction, RegisterEnvi
       do {
         let db = try env.db()
         try env.messenger.register(username: username)
-        var contact = try env.messenger.e2e.tryGet().getContact()
-        try contact.setFact(.username, username)
+        let contact = try env.messenger.myContact()
+        let facts = try contact.getFacts()
         try db.saveContact(Contact(
           id: try contact.getId(),
           marshaled: contact.data,
-          username: username,
+          username: facts.get(.username)?.value,
+          email: facts.get(.email)?.value,
+          phone: facts.get(.phone)?.value,
           createdAt: env.now()
         ))
+        guard facts.get(.username)?.value == username else {
+          throw RegisterState.Error.usernameMismatch(
+            registering: username,
+            registered: facts.get(.username)?.value
+          )
+        }
         fulfill(.success(.finished))
       }
       catch {
@@ -106,6 +118,7 @@ public let registerReducer = Reducer<RegisterState, RegisterAction, RegisterEnvi
     return .none
 
   case .finished:
+    state.isRegistering = false
     return .none
   }
 }
diff --git a/Examples/xx-messenger/Sources/RestoreFeature/RestoreFeature.swift b/Examples/xx-messenger/Sources/RestoreFeature/RestoreFeature.swift
index 66d7df2f0cb2ffc960270caad1aecf6c2da1100a..4d372202180da8adbb37355e78739236b8ff7d6a 100644
--- a/Examples/xx-messenger/Sources/RestoreFeature/RestoreFeature.swift
+++ b/Examples/xx-messenger/Sources/RestoreFeature/RestoreFeature.swift
@@ -24,7 +24,7 @@ public struct RestoreState: Equatable {
   public init(
     file: File? = nil,
     fileImportFailure: String? = nil,
-    restoreFailure: String? = nil,
+    restoreFailures: [String] = [],
     focusedField: Field? = nil,
     isImportingFile: Bool = false,
     passphrase: String = "",
@@ -32,7 +32,7 @@ public struct RestoreState: Equatable {
   ) {
     self.file = file
     self.fileImportFailure = fileImportFailure
-    self.restoreFailure = restoreFailure
+    self.restoreFailures = restoreFailures
     self.focusedField = focusedField
     self.isImportingFile = isImportingFile
     self.passphrase = passphrase
@@ -41,7 +41,7 @@ public struct RestoreState: Equatable {
 
   public var file: File?
   public var fileImportFailure: String?
-  public var restoreFailure: String?
+  public var restoreFailures: [String]
   @BindableState public var focusedField: Field?
   @BindableState public var isImportingFile: Bool
   @BindableState public var passphrase: String
@@ -53,7 +53,7 @@ public enum RestoreAction: Equatable, BindableAction {
   case fileImport(Result<URL, NSError>)
   case restoreTapped
   case finished
-  case failed(NSError)
+  case failed([NSError])
   case binding(BindingAction<RestoreState>)
 }
 
@@ -125,7 +125,7 @@ public let restoreReducer = Reducer<RestoreState, RestoreAction, RestoreEnvironm
     guard let backupData = state.file?.data, backupData.count > 0 else { return .none }
     let backupPassphrase = state.passphrase
     state.isRestoring = true
-    state.restoreFailure = nil
+    state.restoreFailures = []
     return Effect.result {
       do {
         let result = try env.messenger.restoreBackup(
@@ -135,15 +135,28 @@ public let restoreReducer = Reducer<RestoreState, RestoreAction, RestoreEnvironm
         let facts = try env.messenger.ud.tryGet().getFacts()
         try env.db().saveContact(Contact(
           id: try env.messenger.e2e.tryGet().getContact().getId(),
-          username: result.restoredParams.username,
+          username: facts.get(.username)?.value,
           email: facts.get(.email)?.value,
           phone: facts.get(.phone)?.value,
           createdAt: env.now()
         ))
+        try result.restoredContacts.forEach { contactId in
+          if try env.db().fetchContacts(.init(id: [contactId])).isEmpty {
+            try env.db().saveContact(Contact(
+              id: contactId,
+              createdAt: env.now()
+            ))
+          }
+        }
         return .success(.finished)
       } catch {
-        try? env.messenger.destroy()
-        return .success(.failed(error as NSError))
+        var errors = [error as NSError]
+        do {
+          try env.messenger.destroy()
+        } catch {
+          errors.append(error as NSError)
+        }
+        return .success(.failed(errors))
       }
     }
     .subscribe(on: env.bgQueue)
@@ -154,9 +167,9 @@ public let restoreReducer = Reducer<RestoreState, RestoreAction, RestoreEnvironm
     state.isRestoring = false
     return .none
 
-  case .failed(let error):
+  case .failed(let errors):
     state.isRestoring = false
-    state.restoreFailure = error.localizedDescription
+    state.restoreFailures = errors.map(\.localizedDescription)
     return .none
 
   case .binding(_):
diff --git a/Examples/xx-messenger/Sources/RestoreFeature/RestoreView.swift b/Examples/xx-messenger/Sources/RestoreFeature/RestoreView.swift
index 06f7b91515725dcd81157dd876b3bcba2783a8e1..281f3f061e4a3ff5ccc1913bb45e45a03cff6576 100644
--- a/Examples/xx-messenger/Sources/RestoreFeature/RestoreView.swift
+++ b/Examples/xx-messenger/Sources/RestoreFeature/RestoreView.swift
@@ -21,7 +21,7 @@ public struct RestoreView: View {
     var isRestoring: Bool
     var focusedField: RestoreState.Field?
     var fileImportFailure: String?
-    var restoreFailure: String?
+    var restoreFailures: [String]
 
     init(state: RestoreState) {
       file = state.file.map { .init(name: $0.name, size: $0.data.count) }
@@ -30,7 +30,7 @@ public struct RestoreView: View {
       isRestoring = state.isRestoring
       focusedField = state.focusedField
       fileImportFailure = state.fileImportFailure
-      restoreFailure = state.restoreFailure
+      restoreFailures = state.restoreFailures
     }
   }
 
@@ -38,69 +38,9 @@ public struct RestoreView: View {
     WithViewStore(store, observe: ViewState.init) { viewStore in
       NavigationView {
         Form {
-          Section {
-            if let file = viewStore.file {
-              HStack(alignment: .bottom) {
-                Text(file.name)
-                Spacer()
-                Text(format(byteCount: file.size))
-              }
-            }
-
-            Button {
-              viewStore.send(.importFileTapped)
-            } label: {
-              Text("Import backup file")
-            }
-            .fileImporter(
-              isPresented: viewStore.binding(
-                get: \.isImportingFile,
-                send: { .set(\.$isImportingFile, $0) }
-              ),
-              allowedContentTypes: [.data],
-              onCompletion: { result in
-                viewStore.send(.fileImport(result.mapError { $0 as NSError }))
-              }
-            )
-
-            if let failure = viewStore.fileImportFailure {
-              Text("Error: \(failure)")
-            }
-          } header: {
-            Text("File")
-          }
-          .disabled(viewStore.isRestoring)
-
+          fileSection(viewStore)
           if viewStore.file != nil {
-            Section {
-              SecureField("Passphrase", text: viewStore.binding(
-                get: \.passphrase,
-                send: { .set(\.$passphrase, $0) }
-              ))
-              .textContentType(.password)
-              .textInputAutocapitalization(.never)
-              .disableAutocorrection(true)
-              .focused($focusedField, equals: .passphrase)
-
-              Button {
-                viewStore.send(.restoreTapped)
-              } label: {
-                HStack {
-                  Text("Restore")
-                  Spacer()
-                  if viewStore.isRestoring {
-                    ProgressView()
-                  }
-                }
-              }
-
-              if let failure = viewStore.restoreFailure {
-                Text("Error: \(failure)")
-              }
-            } header: {
-              Text("Backup")
-            }
-            .disabled(viewStore.isRestoring)
+            restoreSection(viewStore)
           }
         }
         .toolbar {
@@ -110,7 +50,7 @@ public struct RestoreView: View {
             } label: {
               Text("Cancel")
             }
-            .disabled(viewStore.isRestoring)
+            .disabled(viewStore.isImportingFile || viewStore.isRestoring)
           }
         }
         .navigationTitle("Restore")
@@ -121,6 +61,85 @@ public struct RestoreView: View {
     }
   }
 
+  @ViewBuilder func fileSection(_ viewStore: ViewStore<ViewState, RestoreAction>) -> some View {
+    Section {
+      if let file = viewStore.file {
+        HStack(alignment: .bottom) {
+          Text(file.name)
+          Spacer()
+          Text(format(byteCount: file.size))
+        }
+      } else {
+        Button {
+          viewStore.send(.importFileTapped)
+        } label: {
+          Text("Import backup file")
+        }
+        .fileImporter(
+          isPresented: viewStore.binding(
+            get: \.isImportingFile,
+            send: { .set(\.$isImportingFile, $0) }
+          ),
+          allowedContentTypes: [.data],
+          onCompletion: { result in
+            viewStore.send(.fileImport(result.mapError { $0 as NSError }))
+          }
+        )
+        .disabled(viewStore.isRestoring)
+      }
+    } header: {
+      Text("File")
+    }
+
+    if let failure = viewStore.fileImportFailure {
+      Section {
+        Text(failure)
+      } header: {
+        Text("Error")
+      }
+    }
+  }
+
+  @ViewBuilder func restoreSection(_ viewStore: ViewStore<ViewState, RestoreAction>) -> some View {
+    Section {
+      SecureField("Passphrase", text: viewStore.binding(
+        get: \.passphrase,
+        send: { .set(\.$passphrase, $0) }
+      ))
+      .textContentType(.password)
+      .textInputAutocapitalization(.never)
+      .disableAutocorrection(true)
+      .focused($focusedField, equals: .passphrase)
+      .disabled(viewStore.isRestoring)
+
+      Button {
+        viewStore.send(.restoreTapped)
+      } label: {
+        HStack {
+          Text("Restore")
+          Spacer()
+          if viewStore.isRestoring {
+            ProgressView()
+          }
+        }
+      }
+    } header: {
+      Text("Restore")
+    }
+    .disabled(viewStore.isRestoring)
+
+    if !viewStore.restoreFailures.isEmpty {
+      Section {
+        ForEach(Array(viewStore.restoreFailures.enumerated()), id: \.offset) { _, failure in
+          Text(failure)
+        }
+        .font(.footnote)
+      } header: {
+        Text("Error")
+      }
+    }
+  }
+
   func format(byteCount: Int) -> String {
     let formatter = ByteCountFormatter()
     formatter.allowedUnits = [.useMB, .useKB, .useBytes]
@@ -133,7 +152,19 @@ public struct RestoreView: View {
 public struct RestoreView_Previews: PreviewProvider {
   public static var previews: some View {
     RestoreView(store: Store(
-      initialState: RestoreState(),
+      initialState: RestoreState(
+        file: .init(name: "preview", data: Data()),
+        fileImportFailure: nil,
+        restoreFailures: [
+          "Preview failure 1",
+          "Preview failure 2",
+          "Preview failure 3",
+        ],
+        focusedField: nil,
+        isImportingFile: false,
+        passphrase: "",
+        isRestoring: true
+      ),
       reducer: .empty,
       environment: ()
     ))
diff --git a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
index f2625b91e6a4042624ad68141515ab34ace7c90c..18075179aedc62daff46847052e2bc0071f76b0a 100644
--- a/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
+++ b/Examples/xx-messenger/Sources/SendRequestFeature/SendRequestFeature.swift
@@ -1,4 +1,5 @@
 import AppCore
+import Combine
 import ComposableArchitecture
 import Foundation
 import XCTestDynamicOverlay
@@ -40,7 +41,8 @@ public enum SendRequestAction: Equatable, BindableAction {
   case sendSucceeded
   case sendFailed(String)
   case binding(BindingAction<SendRequestState>)
-  case myContactFetched(XXClient.Contact?)
+  case myContactFetched(XXClient.Contact)
+  case myContactFetchFailed(NSError)
 }
 
 public struct SendRequestEnvironment {
@@ -75,25 +77,30 @@ extension SendRequestEnvironment {
 
 public let sendRequestReducer = Reducer<SendRequestState, SendRequestAction, SendRequestEnvironment>
 { state, action, env in
-  enum DBFetchEffectID {}
-
   switch action {
   case .start:
-    return Effect
-      .catching { try env.messenger.e2e.tryGet().getContact().getId() }
-      .tryMap { try env.db().fetchContactsPublisher(.init(id: [$0])) }
-      .flatMap { $0 }
-      .assertNoFailure()
-      .map(\.first)
-      .map { $0?.marshaled.map { XXClient.Contact.live($0) } }
-      .map(SendRequestAction.myContactFetched)
-      .subscribe(on: env.bgQueue)
-      .receive(on: env.mainQueue)
-      .eraseToEffect()
-      .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
+    return Effect.run { subscriber in
+      do {
+        let contact = try env.messenger.myContact()
+        subscriber.send(.myContactFetched(contact))
+      } catch {
+        subscriber.send(.myContactFetchFailed(error as NSError))
+      }
+      subscriber.send(completion: .finished)
+      return AnyCancellable {}
+    }
+    .receive(on: env.mainQueue)
+    .subscribe(on: env.bgQueue)
+    .eraseToEffect()
 
   case .myContactFetched(let contact):
     state.myContact = contact
+    state.failure = nil
+    return .none
+
+  case .myContactFetchFailed(let failure):
+    state.myContact = nil
+    state.failure = failure.localizedDescription
     return .none
 
   case .sendTapped:
diff --git a/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift b/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift
index 21afbd5409a40c956cce46cc40726996f741cb70..d0c69eb87e2efea29f635fce84656b04d2e35cba 100644
--- a/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/BackupFeatureTests/BackupFeatureTests.swift
@@ -2,7 +2,6 @@ import ComposableArchitecture
 import XCTest
 import XXClient
 import XXMessengerClient
-import XXModels
 @testable import BackupFeature
 
 final class BackupFeatureTests: XCTestCase {
@@ -65,11 +64,7 @@ final class BackupFeatureTests: XCTestCase {
   func testStartBackup() {
     var actions: [Action]!
     var isBackupRunning: [Bool] = [true]
-    let contactID = "contact-id".data(using: .utf8)!
-    let dbContact = XXModels.Contact(
-      id: contactID,
-      username: "db-contact-username"
-    )
+    let username = "test-username"
     let passphrase = "backup-password"
 
     let store = TestStore(
@@ -79,28 +74,23 @@ final class BackupFeatureTests: XCTestCase {
     )
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
+    store.environment.messenger.myContact.run = { includeFacts in
+      actions.append(.didGetMyContact(includingFacts: includeFacts))
+      var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
+      contact.getFactsFromContact.run = { _ in [Fact(type: .username, value: username)] }
+      return contact
+    }
     store.environment.messenger.startBackup.run = { passphrase, params in
       actions.append(.didStartBackup(passphrase: passphrase, params: params))
     }
     store.environment.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact: XXClient.Contact = .unimplemented(Data())
-        contact.getIdFromContact.run = { _ in contactID }
-        return contact
-      }
-      return e2e
-    }
-    store.environment.db.run = {
-      var db: Database = .unimplemented
-      db.fetchContacts.run = { _ in return [dbContact] }
-      return db
-    }
 
     actions = []
+    store.send(.set(\.$focusedField, .passphrase)) {
+      $0.focusedField = .passphrase
+    }
     store.send(.set(\.$passphrase, passphrase)) {
       $0.passphrase = passphrase
     }
@@ -110,12 +100,16 @@ final class BackupFeatureTests: XCTestCase {
     actions = []
     store.send(.startTapped) {
       $0.isStarting = true
+      $0.focusedField = nil
     }
 
     XCTAssertNoDifference(actions, [
+      .didGetMyContact(
+        includingFacts: .types([.username])
+      ),
       .didStartBackup(
         passphrase: passphrase,
-        params: .init(username: dbContact.username!)
+        params: .init(username: username)
       )
     ])
 
@@ -126,9 +120,8 @@ final class BackupFeatureTests: XCTestCase {
     }
   }
 
-  func testStartBackupWithoutDbContact() {
+  func testStartBackupWithoutContactUsername() {
     var isBackupRunning: [Bool] = [false]
-    let contactID = "contact-id".data(using: .utf8)!
 
     let store = TestStore(
       initialState: BackupState(
@@ -139,29 +132,20 @@ final class BackupFeatureTests: XCTestCase {
     )
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
+    store.environment.messenger.myContact.run = { _ in
+      var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
+      contact.getFactsFromContact.run = { _ in [] }
+      return contact
+    }
     store.environment.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact: XXClient.Contact = .unimplemented(Data())
-        contact.getIdFromContact.run = { _ in contactID }
-        return contact
-      }
-      return e2e
-    }
-    store.environment.db.run = {
-      var db: Database = .unimplemented
-      db.fetchContacts.run = { _ in [] }
-      return db
-    }
 
     store.send(.startTapped) {
       $0.isStarting = true
     }
 
-    let failure = BackupState.Error.dbContactNotFound
+    let failure = BackupState.Error.contactUsernameMissing
     store.receive(.didStart(failure: failure as NSError)) {
       $0.isRunning = false
       $0.isStarting = false
@@ -169,13 +153,10 @@ final class BackupFeatureTests: XCTestCase {
     }
   }
 
-  func testStartBackupWithoutDbContactUsername() {
+  func testStartBackupMyContactFailure() {
+    struct Failure: Error {}
+    let failure = Failure()
     var isBackupRunning: [Bool] = [false]
-    let contactID = "contact-id".data(using: .utf8)!
-    let dbContact = XXModels.Contact(
-      id: contactID,
-      username: nil
-    )
 
     let store = TestStore(
       initialState: BackupState(
@@ -186,29 +167,15 @@ final class BackupFeatureTests: XCTestCase {
     )
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
+    store.environment.messenger.myContact.run = { _ in throw failure }
     store.environment.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact: XXClient.Contact = .unimplemented(Data())
-        contact.getIdFromContact.run = { _ in contactID }
-        return contact
-      }
-      return e2e
-    }
-    store.environment.db.run = {
-      var db: Database = .unimplemented
-      db.fetchContacts.run = { _ in [dbContact] }
-      return db
-    }
 
     store.send(.startTapped) {
       $0.isStarting = true
     }
 
-    let failure = BackupState.Error.dbContactUsernameMissing
     store.receive(.didStart(failure: failure as NSError)) {
       $0.isRunning = false
       $0.isStarting = false
@@ -216,15 +183,10 @@ final class BackupFeatureTests: XCTestCase {
     }
   }
 
-  func testStartBackupFailure() {
+  func testStartBackupStartFailure() {
     struct Failure: Error {}
     let failure = Failure()
     var isBackupRunning: [Bool] = [false]
-    let contactID = "contact-id".data(using: .utf8)!
-    let dbContact = XXModels.Contact(
-      id: contactID,
-      username: "db-contact-username"
-    )
 
     let store = TestStore(
       initialState: BackupState(
@@ -235,26 +197,17 @@ final class BackupFeatureTests: XCTestCase {
     )
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
+    store.environment.messenger.myContact.run = { _ in
+      var contact = Contact.unimplemented("data".data(using: .utf8)!)
+      contact.getFactsFromContact.run = { _ in [Fact(type: .username, value: "username")] }
+      return contact
+    }
     store.environment.messenger.startBackup.run = { _, _ in
       throw failure
     }
     store.environment.messenger.isBackupRunning.run = {
       isBackupRunning.removeFirst()
     }
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact: XXClient.Contact = .unimplemented(Data())
-        contact.getIdFromContact.run = { _ in contactID }
-        return contact
-      }
-      return e2e
-    }
-    store.environment.db.run = {
-      var db: Database = .unimplemented
-      db.fetchContacts.run = { _ in return [dbContact] }
-      return db
-    }
 
     store.send(.startTapped) {
       $0.isStarting = true
@@ -459,5 +412,5 @@ private enum Action: Equatable {
   case didResumeBackup
   case didStopBackup
   case didRemoveBackup
-  case didFetchContacts(XXModels.Contact.Query)
+  case didGetMyContact(includingFacts: MessengerMyContact.IncludeFacts?)
 }
diff --git a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
index feeccc98094da76d1f5ebd21122a4b3214afbcb7..c200094f49e9164391cdd20afdc53ed793a9c736 100644
--- a/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/ContactFeatureTests/ContactFeatureTests.swift
@@ -3,6 +3,7 @@ import CheckContactAuthFeature
 import Combine
 import ComposableArchitecture
 import ConfirmRequestFeature
+import ContactLookupFeature
 import CustomDump
 import SendRequestFeature
 import VerifyContactFeature
@@ -99,6 +100,55 @@ final class ContactFeatureTests: XCTestCase {
     XCTAssertNoDifference(dbDidSaveContact, [expectedSavedContact])
   }
 
+  func testLookupTapped() {
+    let contactId = "contact-id".data(using: .utf8)!
+    let store = TestStore(
+      initialState: ContactState(
+        id: contactId
+      ),
+      reducer: contactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.lookupTapped) {
+      $0.lookup = ContactLookupState(id: contactId)
+    }
+  }
+
+  func testLookupDismissed() {
+    let contactId = "contact-id".data(using: .utf8)!
+    let store = TestStore(
+      initialState: ContactState(
+        id: contactId,
+        lookup: ContactLookupState(id: contactId)
+      ),
+      reducer: contactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.lookupDismissed) {
+      $0.lookup = nil
+    }
+  }
+
+  func testLookupDidLookup() {
+    let contactId = "contact-id".data(using: .utf8)!
+    let contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
+    let store = TestStore(
+      initialState: ContactState(
+        id: contactId,
+        lookup: ContactLookupState(id: contactId)
+      ),
+      reducer: contactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.lookup(.didLookup(contact))) {
+      $0.xxContact = contact
+      $0.lookup = nil
+    }
+  }
+
   func testSendRequestWithDBContact() {
     var dbContact = XXModels.Contact(id: "contact-id".data(using: .utf8)!)
     dbContact.marshaled = "contact-data".data(using: .utf8)!
diff --git a/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..76dde8d07350e240ccf86acdbef175834851b56f
--- /dev/null
+++ b/Examples/xx-messenger/Tests/ContactLookupFeatureTests/ContactLookupFeatureTests.swift
@@ -0,0 +1,60 @@
+import ComposableArchitecture
+import XCTest
+import XXClient
+@testable import ContactLookupFeature
+
+final class ContactLookupFeatureTests: XCTestCase {
+  func testLookup() {
+    let id: Data = "1234".data(using: .utf8)!
+    var didLookupId: [Data] = []
+    let lookedUpContact = Contact.unimplemented("123data".data(using: .utf8)!)
+
+    let store = TestStore(
+      initialState: ContactLookupState(id: id),
+      reducer: contactLookupReducer,
+      environment: .unimplemented
+    )
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.messenger.lookupContact.run = { id in
+      didLookupId.append(id)
+      return lookedUpContact
+    }
+
+    store.send(.lookupTapped) {
+      $0.isLookingUp = true
+      $0.failure = nil
+    }
+
+    XCTAssertEqual(didLookupId, [id])
+
+    store.receive(.didLookup(lookedUpContact)) {
+      $0.isLookingUp = false
+      $0.failure = nil
+    }
+  }
+
+  func testLookupFailure() {
+    let id: Data = "1234".data(using: .utf8)!
+    let failure = NSError(domain: "test", code: 0)
+
+    let store = TestStore(
+      initialState: ContactLookupState(id: id),
+      reducer: contactLookupReducer,
+      environment: .unimplemented
+    )
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.messenger.lookupContact.run = { _ in throw failure }
+
+    store.send(.lookupTapped) {
+      $0.isLookingUp = true
+      $0.failure = nil
+    }
+
+    store.receive(.didFail(failure)) {
+      $0.isLookingUp = false
+      $0.failure = failure.localizedDescription
+    }
+  }
+}
diff --git a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
index 0e55329610aeb8b51611cc539447364ba9963d75..830e97156363b151fbff21276169d8dfc2095720 100644
--- a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
@@ -645,6 +645,7 @@ final class MyContactFeatureTests: XCTestCase {
   func testLoadFactsFromClient() {
     let contactId = "contact-id".data(using: .utf8)!
     let dbContact = XXModels.Contact(id: contactId)
+    let username = "user234"
     let email = "test@email.com"
     let phone = "123456789"
 
@@ -672,6 +673,7 @@ final class MyContactFeatureTests: XCTestCase {
       var ud: UserDiscovery = .unimplemented
       ud.getFacts.run = {
         [
+          Fact(type: .username, value: username),
           Fact(type: .email, value: email),
           Fact(type: .phone, value: phone),
         ]
@@ -697,6 +699,7 @@ final class MyContactFeatureTests: XCTestCase {
 
     XCTAssertNoDifference(didFetchContacts, [.init(id: [contactId])])
     var expectedSavedContact = dbContact
+    expectedSavedContact.username = username
     expectedSavedContact.email = email
     expectedSavedContact.phone = phone
     XCTAssertNoDifference(didSaveContact, [expectedSavedContact])
diff --git a/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift b/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
index b156335b3de889ad21d9819e483fc5e27ef7c6ed..e0ffc5ef4fe9a3bc5f9d9f91d288025cd1065c85 100644
--- a/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
@@ -8,38 +8,40 @@ import XXModels
 
 final class RegisterFeatureTests: XCTestCase {
   func testRegister() throws {
+    let now = Date()
+    let username = "registering-username"
+    let myContactId = "my-contact-id".data(using: .utf8)!
+    let myContactData = "my-contact-data".data(using: .utf8)!
+    let myContactUsername = username
+    let myContactEmail = "my-contact-email"
+    let myContactPhone = "my-contact-phone"
+    let myContactFacts = [
+      Fact(type: .username, value: myContactUsername),
+      Fact(type: .email, value: myContactEmail),
+      Fact(type: .phone, value: myContactPhone),
+    ]
+
+    var messengerDidRegisterUsername: [String] = []
+    var didGetMyContact: [MessengerMyContact.IncludeFacts?] = []
+    var dbDidSaveContact: [XXModels.Contact] = []
+
     let store = TestStore(
       initialState: RegisterState(),
       reducer: registerReducer,
       environment: .unimplemented
     )
-
-    let now = Date()
-    let mainQueue = DispatchQueue.test
-    let bgQueue = DispatchQueue.test
-    var didSetFactsOnContact: [[XXClient.Fact]] = []
-    var dbDidSaveContact: [XXModels.Contact] = []
-    var messengerDidRegisterUsername: [String] = []
-
     store.environment.now = { now }
-    store.environment.mainQueue = mainQueue.eraseToAnyScheduler()
-    store.environment.bgQueue = bgQueue.eraseToAnyScheduler()
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
     store.environment.messenger.register.run = { username in
       messengerDidRegisterUsername.append(username)
     }
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!)
-        contact.getIdFromContact.run = { _ in "contact-id".data(using: .utf8)! }
-        contact.getFactsFromContact.run = { _ in [] }
-        contact.setFactsOnContact.run = { data, facts in
-          didSetFactsOnContact.append(facts)
-          return data
-        }
-        return contact
-      }
-      return e2e
+    store.environment.messenger.myContact.run = { includeFacts in
+      didGetMyContact.append(includeFacts)
+      var contact = XXClient.Contact.unimplemented(myContactData)
+      contact.getIdFromContact.run = { _ in myContactId }
+      contact.getFactsFromContact.run = { _ in myContactFacts }
+      return contact
     }
     store.environment.db.run = {
       var db: Database = .unimplemented
@@ -50,33 +52,34 @@ final class RegisterFeatureTests: XCTestCase {
       return db
     }
 
-    store.send(.set(\.$username, "NewUser")) {
-      $0.username = "NewUser"
+    store.send(.set(\.$focusedField, .username)) {
+      $0.focusedField = .username
+    }
+
+    store.send(.set(\.$username, myContactUsername)) {
+      $0.username = myContactUsername
     }
 
     store.send(.registerTapped) {
+      $0.focusedField = nil
       $0.isRegistering = true
     }
 
-    XCTAssertNoDifference(messengerDidRegisterUsername, [])
-    XCTAssertNoDifference(dbDidSaveContact, [])
-
-    bgQueue.advance()
-
-    XCTAssertNoDifference(messengerDidRegisterUsername, ["NewUser"])
-    XCTAssertNoDifference(didSetFactsOnContact, [[Fact(type: .username, value: "NewUser")]])
+    XCTAssertNoDifference(messengerDidRegisterUsername, [username])
     XCTAssertNoDifference(dbDidSaveContact, [
       XXModels.Contact(
-        id: "contact-id".data(using: .utf8)!,
-        marshaled: "contact-data".data(using: .utf8)!,
-        username: "NewUser",
+        id: myContactId,
+        marshaled: myContactData,
+        username: myContactUsername,
+        email: myContactEmail,
+        phone: myContactPhone,
         createdAt: now
       )
     ])
 
-    mainQueue.advance()
-
-    store.receive(.finished)
+    store.receive(.finished) {
+      $0.isRegistering = false
+    }
   }
 
   func testGetDbFailure() throws {
@@ -139,4 +142,78 @@ final class RegisterFeatureTests: XCTestCase {
       $0.failure = error.localizedDescription
     }
   }
+
+  func testRegisterUsernameMismatchFailure() throws {
+    let now = Date()
+    let username = "registering-username"
+    let myContactId = "my-contact-id".data(using: .utf8)!
+    let myContactData = "my-contact-data".data(using: .utf8)!
+    let myContactUsername = "my-contact-username"
+    let myContactEmail = "my-contact-email"
+    let myContactPhone = "my-contact-phone"
+    let myContactFacts = [
+      Fact(type: .username, value: myContactUsername),
+      Fact(type: .email, value: myContactEmail),
+      Fact(type: .phone, value: myContactPhone),
+    ]
+
+    var messengerDidRegisterUsername: [String] = []
+    var didGetMyContact: [MessengerMyContact.IncludeFacts?] = []
+    var dbDidSaveContact: [XXModels.Contact] = []
+
+    let store = TestStore(
+      initialState: RegisterState(
+        username: username
+      ),
+      reducer: registerReducer,
+      environment: .unimplemented
+    )
+    store.environment.now = { now }
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.messenger.register.run = { username in
+      messengerDidRegisterUsername.append(username)
+    }
+    store.environment.messenger.myContact.run = { includeFacts in
+      didGetMyContact.append(includeFacts)
+      var contact = XXClient.Contact.unimplemented(myContactData)
+      contact.getIdFromContact.run = { _ in myContactId }
+      contact.getFactsFromContact.run = { _ in myContactFacts }
+      return contact
+    }
+    store.environment.db.run = {
+      var db: Database = .unimplemented
+      db.saveContact.run = { contact in
+        dbDidSaveContact.append(contact)
+        return contact
+      }
+      return db
+    }
+
+    store.send(.registerTapped) {
+      $0.focusedField = nil
+      $0.isRegistering = true
+    }
+
+    XCTAssertNoDifference(messengerDidRegisterUsername, [username])
+    XCTAssertNoDifference(dbDidSaveContact, [
+      XXModels.Contact(
+        id: myContactId,
+        marshaled: myContactData,
+        username: myContactUsername,
+        email: myContactEmail,
+        phone: myContactPhone,
+        createdAt: now
+      )
+    ])
+
+    let failure = RegisterState.Error.usernameMismatch(
+      registering: username,
+      registered: myContactUsername
+    )
+    store.receive(.failed(failure.localizedDescription)) {
+      $0.isRegistering = false
+      $0.failure = failure.localizedDescription
+    }
+  }
 }
diff --git a/Examples/xx-messenger/Tests/RestoreFeatureTests/RestoreFeatureTests.swift b/Examples/xx-messenger/Tests/RestoreFeatureTests/RestoreFeatureTests.swift
index 9b0a7b87928e8568acf78c8f63077920a8c9fd2e..716d7650255b277cad37fb40ad5a73c4aee5bace 100644
--- a/Examples/xx-messenger/Tests/RestoreFeatureTests/RestoreFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/RestoreFeatureTests/RestoreFeatureTests.swift
@@ -80,12 +80,17 @@ final class RestoreFeatureTests: XCTestCase {
     let backupData = "backup-data".data(using: .utf8)!
     let backupPassphrase = "backup-passphrase"
     let restoredFacts = [
-      Fact(type: .email, value: "restored-email"),
-      Fact(type: .phone, value: "restored-phone"),
+      Fact(type: .username, value: "restored-fact-username"),
+      Fact(type: .email, value: "restored-fact-email"),
+      Fact(type: .phone, value: "restored-fact-phone"),
     ]
     let restoreResult = MessengerRestoreBackup.Result(
-      restoredParams: BackupParams(username: "restored-username"),
-      restoredContacts: []
+      restoredParams: BackupParams(username: "restored-param-username"),
+      restoredContacts: [
+        "contact-1-id".data(using: .utf8)!,
+        "contact-2-id".data(using: .utf8)!,
+        "contact-3-id".data(using: .utf8)!,
+      ]
     )
     let now = Date()
     let contactId = "contact-id".data(using: .utf8)!
@@ -93,6 +98,7 @@ final class RestoreFeatureTests: XCTestCase {
     var udFacts: [Fact] = []
     var didRestoreWithData: [Data] = []
     var didRestoreWithPassphrase: [String] = []
+    var didFetchContacts: [XXModels.Contact.Query] = []
     var didSaveContact: [XXModels.Contact] = []
 
     let store = TestStore(
@@ -128,6 +134,10 @@ final class RestoreFeatureTests: XCTestCase {
     }
     store.environment.db.run = {
       var db: Database = .unimplemented
+      db.fetchContacts.run = { query in
+        didFetchContacts.append(query)
+        return []
+      }
       db.saveContact.run = { contact in
         didSaveContact.append(contact)
         return contact
@@ -145,13 +155,32 @@ final class RestoreFeatureTests: XCTestCase {
 
     XCTAssertNoDifference(didRestoreWithData, [backupData])
     XCTAssertNoDifference(didRestoreWithPassphrase, [backupPassphrase])
-    XCTAssertNoDifference(didSaveContact, [Contact(
-      id: contactId,
-      username: restoreResult.restoredParams.username,
-      email: restoredFacts.get(.email)?.value,
-      phone: restoredFacts.get(.phone)?.value,
-      createdAt: now
-    )])
+    XCTAssertNoDifference(didFetchContacts, [
+      .init(id: [restoreResult.restoredContacts[0]]),
+      .init(id: [restoreResult.restoredContacts[1]]),
+      .init(id: [restoreResult.restoredContacts[2]]),
+    ])
+    XCTAssertNoDifference(didSaveContact, [
+      Contact(
+        id: contactId,
+        username: restoredFacts.get(.username)?.value,
+        email: restoredFacts.get(.email)?.value,
+        phone: restoredFacts.get(.phone)?.value,
+        createdAt: now
+      ),
+      Contact(
+        id: restoreResult.restoredContacts[0],
+        createdAt: now
+      ),
+      Contact(
+        id: restoreResult.restoredContacts[1],
+        createdAt: now
+      ),
+      Contact(
+        id: restoreResult.restoredContacts[2],
+        createdAt: now
+      ),
+    ])
 
     store.receive(.finished) {
       $0.isRestoring = false
@@ -171,10 +200,10 @@ final class RestoreFeatureTests: XCTestCase {
   }
 
   func testRestoreFailure() {
-    struct Failure: Error {}
-    let failure = Failure()
-
-    var didDestroyMessenger = 0
+    enum Failure: Error {
+      case restore
+      case destroy
+    }
 
     let store = TestStore(
       initialState: RestoreState(
@@ -186,18 +215,19 @@ final class RestoreFeatureTests: XCTestCase {
 
     store.environment.bgQueue = .immediate
     store.environment.mainQueue = .immediate
-    store.environment.messenger.restoreBackup.run = { _, _ in throw failure }
-    store.environment.messenger.destroy.run = { didDestroyMessenger += 1 }
+    store.environment.messenger.restoreBackup.run = { _, _ in throw Failure.restore }
+    store.environment.messenger.destroy.run = { throw Failure.destroy }
 
     store.send(.restoreTapped) {
       $0.isRestoring = true
     }
 
-    XCTAssertEqual(didDestroyMessenger, 1)
-
-    store.receive(.failed(failure as NSError)) {
+    store.receive(.failed([Failure.restore as NSError, Failure.destroy as NSError])) {
       $0.isRestoring = false
-      $0.restoreFailure = failure.localizedDescription
+      $0.restoreFailures = [
+        Failure.restore.localizedDescription,
+        Failure.destroy.localizedDescription,
+      ]
     }
   }
 }
diff --git a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
index 9b15f6cd39884e45f7214875ba586cbb0e2b7712..4c68abab06a609346b47b4fe472d5f377417c2f5 100644
--- a/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/SendRequestFeatureTests/SendRequestFeatureTests.swift
@@ -3,11 +3,16 @@ import ComposableArchitecture
 import CustomDump
 import XCTest
 import XXClient
+import XXMessengerClient
 import XXModels
 @testable import SendRequestFeature
 
 final class SendRequestFeatureTests: XCTestCase {
   func testStart() {
+    let myContact = XXClient.Contact.unimplemented("my-contact-data".data(using: .utf8)!)
+
+    var didGetMyContact: [MessengerMyContact.IncludeFacts?] = []
+
     let store = TestStore(
       initialState: SendRequestState(
         contact: .unimplemented("contact-data".data(using: .utf8)!)
@@ -15,47 +20,41 @@ final class SendRequestFeatureTests: XCTestCase {
       reducer: sendRequestReducer,
       environment: .unimplemented
     )
-
-    var dbDidFetchContacts: [XXModels.Contact.Query] = []
-    let dbContactsPublisher = PassthroughSubject<[XXModels.Contact], Error>()
-
     store.environment.mainQueue = .immediate
     store.environment.bgQueue = .immediate
-    store.environment.messenger.e2e.get = {
-      var e2e: E2E = .unimplemented
-      e2e.getContact.run = {
-        var contact: XXClient.Contact = .unimplemented("my-contact-data".data(using: .utf8)!)
-        contact.getIdFromContact.run = { _ in "my-contact-id".data(using: .utf8)! }
-        return contact
-      }
-      return e2e
-    }
-    store.environment.db.run = {
-      var db: Database = .unimplemented
-      db.fetchContactsPublisher.run = { query in
-        dbDidFetchContacts.append(query)
-        return dbContactsPublisher.eraseToAnyPublisher()
-      }
-      return db
+    store.environment.messenger.myContact.run = { includeFacts in
+      didGetMyContact.append(includeFacts)
+      return myContact
     }
 
     store.send(.start)
 
-    XCTAssertNoDifference(dbDidFetchContacts, [.init(id: ["my-contact-id".data(using: .utf8)!])])
+    store.receive(.myContactFetched(myContact)) {
+      $0.myContact = myContact
+    }
+  }
 
-    dbContactsPublisher.send([])
+  func testMyContactFailure() {
+    struct Failure: Error {}
+    let failure = Failure()
 
-    store.receive(.myContactFetched(nil))
+    let store = TestStore(
+      initialState: SendRequestState(
+        contact: .unimplemented("contact-data".data(using: .utf8)!)
+      ),
+      reducer: sendRequestReducer,
+      environment: .unimplemented
+    )
+    store.environment.mainQueue = .immediate
+    store.environment.bgQueue = .immediate
+    store.environment.messenger.myContact.run = { _ in throw failure }
 
-    var myDbContact = XXModels.Contact(id: "my-contact-id".data(using: .utf8)!)
-    myDbContact.marshaled = "my-contact-data".data(using: .utf8)!
-    dbContactsPublisher.send([myDbContact])
+    store.send(.start)
 
-    store.receive(.myContactFetched(.live("my-contact-data".data(using: .utf8)!))) {
-      $0.myContact = .live("my-contact-data".data(using: .utf8)!)
+    store.receive(.myContactFetchFailed(failure as NSError)) {
+      $0.myContact = nil
+      $0.failure = failure.localizedDescription
     }
-
-    dbContactsPublisher.send(completion: .finished)
   }
 
   func testSendRequest() {
diff --git a/Sources/XXClient/Callbacks/UdMultiLookupCallback.swift b/Sources/XXClient/Callbacks/UdMultiLookupCallback.swift
index 1782c01ef83d2a74feef73f490e422f201c67c9a..cc40b60695912e2b5f76663d214a9592f854f248 100644
--- a/Sources/XXClient/Callbacks/UdMultiLookupCallback.swift
+++ b/Sources/XXClient/Callbacks/UdMultiLookupCallback.swift
@@ -49,21 +49,21 @@ extension UdMultiLookupCallback {
         if let err = err {
           result.errors.append(err as NSError)
         }
-        if let contactListJSON = contactListJSON {
-          do {
-            result.contacts = try JSONDecoder()
-              .decode([Data].self, from: contactListJSON)
-              .map { Contact.live($0) }
-          } catch {
-            result.errors.append(error as NSError)
+        do {
+          if let data = contactListJSON,
+             let contactListJSON = try JSONDecoder().decode([Data]?.self, from: data) {
+            result.contacts = contactListJSON.map { Contact.live($0) }
           }
+        } catch {
+          result.errors.append(error as NSError)
         }
-        if let failedIDs = failedIDs {
-          do {
-            result.failedIds = try JSONDecoder().decode([Data].self, from: failedIDs)
-          } catch {
-            result.errors.append(error as NSError)
+        do {
+          if let data = failedIDs,
+             let failedIDs = try JSONDecoder().decode([Data]?.self, from: data) {
+            result.failedIds = failedIDs
           }
+        } catch {
+            result.errors.append(error as NSError)
         }
         callback.handle(result)
       }