diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index b93b0359ce10e8050dce8d07f8dfd5f8d0d7b763..d824d6d400b402270d341bb43fbd5f363c84a879 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -125,7 +125,12 @@ extension AppEnvironment {
               bgQueue: bgQueue,
               contact: { contactEnvironment },
               myContact: {
-                MyContactEnvironment()
+                MyContactEnvironment(
+                  messenger: messenger,
+                  db: dbManager.getDB,
+                  mainQueue: mainQueue,
+                  bgQueue: bgQueue
+                )
               }
             )
           },
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
index 8d335305decc660886a92c5d61f32db4329b4702..c2cfe972977239d535af47d21a18b3c2f5963402 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactFeature.swift
@@ -1,28 +1,115 @@
+import AppCore
 import ComposableArchitecture
+import Foundation
 import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
 
 public struct MyContactState: Equatable {
-  public init() {}
+  public enum Field: String, Hashable {
+    case email
+    case phone
+  }
+
+  public init(
+    contact: XXModels.Contact? = nil,
+    focusedField: Field? = nil,
+    email: String = "",
+    phone: String = ""
+  ) {
+    self.contact = contact
+    self.focusedField = focusedField
+    self.email = email
+    self.phone = phone
+  }
+
+  public var contact: XXModels.Contact?
+  @BindableState public var focusedField: Field?
+  @BindableState public var email: String
+  @BindableState public var phone: String
 }
 
-public enum MyContactAction: Equatable {
+public enum MyContactAction: Equatable, BindableAction {
   case start
+  case contactFetched(XXModels.Contact?)
+  case registerEmailTapped
+  case unregisterEmailTapped
+  case registerPhoneTapped
+  case unregisterPhoneTapped
+  case loadFactsTapped
+  case binding(BindingAction<MyContactState>)
 }
 
 public struct MyContactEnvironment {
-  public init() {}
+  public init(
+    messenger: Messenger,
+    db: DBManagerGetDB,
+    mainQueue: AnySchedulerOf<DispatchQueue>,
+    bgQueue: AnySchedulerOf<DispatchQueue>
+  ) {
+    self.messenger = messenger
+    self.db = db
+    self.mainQueue = mainQueue
+    self.bgQueue = bgQueue
+  }
+
+  public var messenger: Messenger
+  public var db: DBManagerGetDB
+  public var mainQueue: AnySchedulerOf<DispatchQueue>
+  public var bgQueue: AnySchedulerOf<DispatchQueue>
 }
 
 #if DEBUG
 extension MyContactEnvironment {
-  public static let unimplemented = MyContactEnvironment()
+  public static let unimplemented = MyContactEnvironment(
+    messenger: .unimplemented,
+    db: .unimplemented,
+    mainQueue: .unimplemented,
+    bgQueue: .unimplemented
+  )
 }
 #endif
 
 public let myContactReducer = Reducer<MyContactState, MyContactAction, MyContactEnvironment>
 { 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(MyContactAction.contactFetched)
+      .subscribe(on: env.bgQueue)
+      .receive(on: env.mainQueue)
+      .eraseToEffect()
+      .cancellable(id: DBFetchEffectID.self, cancelInFlight: true)
+
+  case .contactFetched(let contact):
+    state.contact = contact
+    return .none
+
+  case .registerEmailTapped:
+    return .none
+
+  case .unregisterEmailTapped:
+    return .none
+
+  case .registerPhoneTapped:
+    return .none
+
+  case .unregisterPhoneTapped:
+    return .none
+
+  case .loadFactsTapped:
+    return .none
+
+  case .binding(_):
     return .none
   }
 }
+.binding()
diff --git a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
index d5092e4bfd748c4ff0c45d18797460f9ed4e612b..0887f682e135f943c0d280e2eb1335268d519866 100644
--- a/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
+++ b/Examples/xx-messenger/Sources/MyContactFeature/MyContactView.swift
@@ -1,5 +1,6 @@
 import ComposableArchitecture
 import SwiftUI
+import XXModels
 
 public struct MyContactView: View {
   public init(store: Store<MyContactState, MyContactAction>) {
@@ -7,17 +8,113 @@ public struct MyContactView: View {
   }
 
   let store: Store<MyContactState, MyContactAction>
+  @FocusState var focusedField: MyContactState.Field?
 
   struct ViewState: Equatable {
-    init(state: MyContactState) {}
+    init(state: MyContactState) {
+      contact = state.contact
+      focusedField = state.focusedField
+      email = state.email
+      phone = state.phone
+    }
+
+    var contact: XXModels.Contact?
+    var focusedField: MyContactState.Field?
+    var email: String
+    var phone: String
   }
 
   public var body: some View {
     WithViewStore(store, observe: ViewState.init) { viewStore in
       Form {
+        Section {
+          Text(viewStore.contact?.username ?? "")
+        } header: {
+          Label("Username", systemImage: "person")
+        }
+
+        Section {
+          if let contact = viewStore.contact {
+            if let email = contact.email {
+              Text(email)
+              Button(role: .destructive) {
+                viewStore.send(.unregisterEmailTapped)
+              } label: {
+                Text("Unregister")
+              }
+            } else {
+              TextField(
+                text: viewStore.binding(
+                  get: \.email,
+                  send: { MyContactAction.set(\.$email, $0) }
+                ),
+                prompt: Text("Enter email"),
+                label: { Text("Email") }
+              )
+              .focused($focusedField, equals: .email)
+              .textInputAutocapitalization(.never)
+              .disableAutocorrection(true)
+              Button {
+                viewStore.send(.registerEmailTapped)
+              } label: {
+                Text("Register")
+              }
+            }
+          } else {
+            Text("")
+          }
+        } header: {
+          Label("Email", systemImage: "envelope")
+        }
 
+        Section {
+          if let contact = viewStore.contact {
+            if let phone = contact.phone {
+              Text(phone)
+              Button(role: .destructive) {
+                viewStore.send(.unregisterPhoneTapped)
+              } label: {
+                Text("Unregister")
+              }
+            } else {
+              TextField(
+                text: viewStore.binding(
+                  get: \.phone,
+                  send: { MyContactAction.set(\.$phone, $0) }
+                ),
+                prompt: Text("Enter phone"),
+                label: { Text("Phone") }
+              )
+              .focused($focusedField, equals: .phone)
+              .textInputAutocapitalization(.never)
+              .disableAutocorrection(true)
+              Button {
+                viewStore.send(.registerPhoneTapped)
+              } label: {
+                Text("Register")
+              }
+            }
+          } else {
+            Text("")
+          }
+        } header: {
+          Label("Phone", systemImage: "phone")
+        }
+
+        Section {
+          Button {
+            viewStore.send(.loadFactsTapped)
+          } label: {
+            Text("Load facts from client")
+          }
+        } header: {
+          Text("Actions")
+        }
       }
       .navigationTitle("My Contact")
+      .task { viewStore.send(.start) }
+      .onChange(of: viewStore.focusedField) { focusedField = $0 }
+      .onChange(of: focusedField) { viewStore.send(.set(\.$focusedField, $0)) }
     }
   }
 }
@@ -25,11 +122,13 @@ public struct MyContactView: View {
 #if DEBUG
 public struct MyContactView_Previews: PreviewProvider {
   public static var previews: some View {
-    MyContactView(store: Store(
-      initialState: MyContactState(),
-      reducer: .empty,
-      environment: ()
-    ))
+    NavigationView {
+      MyContactView(store: Store(
+        initialState: MyContactState(),
+        reducer: .empty,
+        environment: ()
+      ))
+    }
   }
 }
 #endif
diff --git a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
index 6807dcd65937aaa5842b4a1d57cf3a4ea995f521..eba876a9e49f21d5a590866fd4cec4efa9775c8a 100644
--- a/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/MyContactFeatureTests/MyContactFeatureTests.swift
@@ -1,15 +1,122 @@
+import Combine
 import ComposableArchitecture
+import CustomDump
 import XCTest
+import XXClient
+import XXMessengerClient
+import XXModels
 @testable import MyContactFeature
 
 final class MyContactFeatureTests: XCTestCase {
   func testStart() {
+    let contactId = "contact-id".data(using: .utf8)!
+
     let store = TestStore(
       initialState: MyContactState(),
       reducer: myContactReducer,
       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(Data())
+        contact.getIdFromContact.run = { _ in contactId }
+        return contact
+      }
+      return e2e
+    }
+    store.environment.db.run = {
+      var db: Database = .failing
+      db.fetchContactsPublisher.run = { query in
+        dbDidFetchContacts.append(query)
+        return dbContactsPublisher.eraseToAnyPublisher()
+      }
+      return db
+    }
+
     store.send(.start)
+
+    XCTAssertNoDifference(dbDidFetchContacts, [.init(id: [contactId])])
+
+    dbContactsPublisher.send([])
+
+    store.receive(.contactFetched(nil))
+
+    let contact = XXModels.Contact(id: contactId)
+    dbContactsPublisher.send([contact])
+
+    store.receive(.contactFetched(contact)) {
+      $0.contact = contact
+    }
+
+    dbContactsPublisher.send(completion: .finished)
+  }
+
+  func testRegisterEmail() {
+    let email = "test@email.com"
+
+    let store = TestStore(
+      initialState: MyContactState(),
+      reducer: myContactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.set(\.$email, email)) {
+      $0.email = email
+    }
+
+    store.send(.registerEmailTapped)
+  }
+
+  func testUnregisterEmail() {
+    let store = TestStore(
+      initialState: MyContactState(),
+      reducer: myContactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.unregisterEmailTapped)
+  }
+
+  func testRegisterPhone() {
+    let phone = "123456789"
+
+    let store = TestStore(
+      initialState: MyContactState(),
+      reducer: myContactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.set(\.$phone, phone)) {
+      $0.phone = phone
+    }
+
+    store.send(.registerPhoneTapped)
+  }
+
+  func testUnregisterPhone() {
+    let store = TestStore(
+      initialState: MyContactState(),
+      reducer: myContactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.unregisterPhoneTapped)
+  }
+
+  func testLoadFactsFromClient() {
+    let store = TestStore(
+      initialState: MyContactState(),
+      reducer: myContactReducer,
+      environment: .unimplemented
+    )
+
+    store.send(.loadFactsTapped)
   }
 }