diff --git a/Examples/xx-messenger/Package.swift b/Examples/xx-messenger/Package.swift
index f7e0d0399b2b67ef32c8bece58cfb102e76864a2..8f1e26f79d8f80884a0e60b4a81a249fb00f76d8 100644
--- a/Examples/xx-messenger/Package.swift
+++ b/Examples/xx-messenger/Package.swift
@@ -106,8 +106,10 @@ let package = Package(
     .target(
       name: "RegisterFeature",
       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
     ),
diff --git a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
index d3cc134a7dbca79b4d9e75472eb26697f08a455b..19f1b7f5a750f278ca41ff031acf08409cccaa02 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppEnvironment+Live.swift
@@ -33,11 +33,14 @@ extension AppEnvironment {
       home: {
         HomeEnvironment(
           messenger: messenger,
+          db: dbManager.getDB,
           mainQueue: mainQueue,
           bgQueue: bgQueue,
           register: {
             RegisterEnvironment(
               messenger: messenger,
+              db: dbManager.getDB,
+              now: Date.init,
               mainQueue: mainQueue,
               bgQueue: bgQueue
             )
diff --git a/Examples/xx-messenger/Sources/AppFeature/AppFeature.swift b/Examples/xx-messenger/Sources/AppFeature/AppFeature.swift
index 535d69fcbc3044d7698040497d5eba6020d5e426..582478d479dcc31b5e12a491e6843919bdd4aa43 100644
--- a/Examples/xx-messenger/Sources/AppFeature/AppFeature.swift
+++ b/Examples/xx-messenger/Sources/AppFeature/AppFeature.swift
@@ -68,7 +68,7 @@ extension AppEnvironment {
 let appReducer = Reducer<AppState, AppAction, AppEnvironment>
 { state, action, env in
   switch action {
-  case .start, .welcome(.finished), .restore(.finished):
+  case .start, .welcome(.finished), .restore(.finished), .home(.didDeleteAccount):
     state.screen = .loading
     return .run { subscriber in
       do {
diff --git a/Examples/xx-messenger/Sources/HomeFeature/Alerts.swift b/Examples/xx-messenger/Sources/HomeFeature/Alerts.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a3347be43974d0e957ea1850369469360bb70311
--- /dev/null
+++ b/Examples/xx-messenger/Sources/HomeFeature/Alerts.swift
@@ -0,0 +1,22 @@
+import ComposableArchitecture
+
+extension AlertState {
+  public static func confirmAccountDeletion() -> AlertState<HomeAction> {
+    AlertState<HomeAction>(
+      title: TextState("Delete Account"),
+      message: TextState("This will permanently delete your account and can't be undone."),
+      buttons: [
+        .destructive(TextState("Delete"), action: .send(.deleteAccountConfirmed)),
+        .cancel(TextState("Cancel"))
+      ]
+    )
+  }
+
+  public static func accountDeletionFailed(_ error: Error) -> AlertState<HomeAction> {
+    AlertState<HomeAction>(
+      title: TextState("Error"),
+      message: TextState(error.localizedDescription),
+      buttons: []
+    )
+  }
+}
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
index 29abfb6ba9d977e0e87b0cb31bf7eca167b15886..279a5628bd12f2e1a6e18beb6940b1388a92f455 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeFeature.swift
@@ -1,3 +1,4 @@
+import AppCore
 import Combine
 import ComposableArchitecture
 import ComposablePresentation
@@ -8,22 +9,28 @@ import XXMessengerClient
 
 public struct HomeState: Equatable {
   public init(
-    username: String? = nil,
     failure: String? = nil,
-    register: RegisterState? = nil
+    register: RegisterState? = nil,
+    alert: AlertState<HomeAction>? = nil,
+    isDeletingAccount: Bool = false
   ) {
-    self.username = username
     self.failure = failure
     self.register = register
+    self.alert = alert
+    self.isDeletingAccount = isDeletingAccount
   }
 
-  @BindableState public var username: String?
   @BindableState public var failure: String?
   @BindableState public var register: RegisterState?
+  @BindableState public var alert: AlertState<HomeAction>?
+  @BindableState public var isDeletingAccount: Bool
 }
 
 public enum HomeAction: Equatable, BindableAction {
   case start
+  case deleteAccountButtonTapped
+  case deleteAccountConfirmed
+  case didDeleteAccount
   case binding(BindingAction<HomeState>)
   case register(RegisterAction)
 }
@@ -31,17 +38,20 @@ public enum HomeAction: Equatable, BindableAction {
 public struct HomeEnvironment {
   public init(
     messenger: Messenger,
+    db: DBManagerGetDB,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>,
     register: @escaping () -> RegisterEnvironment
   ) {
     self.messenger = messenger
+    self.db = db
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
     self.register = register
   }
 
   public var messenger: Messenger
+  public var db: DBManagerGetDB
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
   public var register: () -> RegisterEnvironment
@@ -50,6 +60,7 @@ public struct HomeEnvironment {
 extension HomeEnvironment {
   public static let unimplemented = HomeEnvironment(
     messenger: .unimplemented,
+    db: .unimplemented,
     mainQueue: .unimplemented,
     bgQueue: .unimplemented,
     register: { .unimplemented }
@@ -76,14 +87,36 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
           }
           try env.messenger.logIn()
         }
+      } catch {
+        subscriber.send(.set(\.$failure, error.localizedDescription))
+      }
+      subscriber.send(completion: .finished)
+      return AnyCancellable {}
+    }
+    .subscribe(on: env.bgQueue)
+    .receive(on: env.mainQueue)
+    .eraseToEffect()
+
+  case .deleteAccountButtonTapped:
+    state.alert = .confirmAccountDeletion()
+    return .none
 
-        if let contact = env.messenger.e2e()?.getContact(),
-           let facts = try? contact.getFacts(),
-           let username = facts.first(where: { $0.type == 0 })?.fact {
-          subscriber.send(.set(\.$username, username))
+  case .deleteAccountConfirmed:
+    state.isDeletingAccount = true
+    return .run { subscriber in
+      do {
+        let contactId = try env.messenger.e2e.tryGet().getContact().getId()
+        let contact = try env.db().fetchContacts(.init(id: [contactId])).first
+        if let username = contact?.username {
+          let ud = try env.messenger.ud.tryGet()
+          try ud.permanentDeleteAccount(username: Fact(fact: username, type: 0))
         }
+        try env.messenger.destroy()
+        try env.db().drop()
+        subscriber.send(.didDeleteAccount)
       } catch {
-        subscriber.send(.set(\.$failure, error.localizedDescription))
+        subscriber.send(.set(\.$isDeletingAccount, false))
+        subscriber.send(.set(\.$alert, .accountDeletionFailed(error)))
       }
       subscriber.send(completion: .finished)
       return AnyCancellable {}
@@ -92,6 +125,10 @@ public let homeReducer = Reducer<HomeState, HomeAction, HomeEnvironment>
     .receive(on: env.mainQueue)
     .eraseToEffect()
 
+  case .didDeleteAccount:
+    state.isDeletingAccount = false
+    return .none
+
   case .register(.finished):
     state.register = nil
     return Effect(value: .start)
diff --git a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
index e40bb1db3982e1673ca2c77d6b8b0e72fa697da9..f73f6b8a9ff2696763a995f3358032d3229d2ca3 100644
--- a/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
+++ b/Examples/xx-messenger/Sources/HomeFeature/HomeView.swift
@@ -11,12 +11,12 @@ public struct HomeView: View {
   let store: Store<HomeState, HomeAction>
 
   struct ViewState: Equatable {
-    var username: String?
     var failure: String?
+    var isDeletingAccount: Bool
 
     init(state: HomeState) {
-      username = state.username
       failure = state.failure
+      isDeletingAccount = state.isDeletingAccount
     }
   }
 
@@ -24,14 +24,6 @@ public struct HomeView: View {
     WithViewStore(store.scope(state: ViewState.init)) { viewStore in
       NavigationView {
         Form {
-          if let username = viewStore.username {
-            Section {
-              Text(username)
-            } header: {
-              Text("Username")
-            }
-          }
-
           if let failure = viewStore.failure {
             Section {
               Text(failure)
@@ -44,8 +36,29 @@ public struct HomeView: View {
               Text("Error")
             }
           }
+
+          Section {
+            Button(role: .destructive) {
+              viewStore.send(.deleteAccountButtonTapped)
+            } label: {
+              HStack {
+                Text("Delete Account")
+                Spacer()
+                if viewStore.isDeletingAccount {
+                  ProgressView()
+                }
+              }
+            }
+            .disabled(viewStore.isDeletingAccount)
+          } header: {
+            Text("Account")
+          }
         }
         .navigationTitle("Home")
+        .alert(
+          store.scope(state: \.alert),
+          dismiss: HomeAction.set(\.$alert, nil)
+        )
       }
       .navigationViewStyle(.stack)
       .task { viewStore.send(.start) }
diff --git a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
index f929d18fd5bdc1a004cd05f4bb366b5c0d835c03..a8d3280c5e321cb78ade668570dcc40159f0b7b7 100644
--- a/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
+++ b/Examples/xx-messenger/Sources/RegisterFeature/RegisterFeature.swift
@@ -1,6 +1,9 @@
+import AppCore
 import ComposableArchitecture
 import SwiftUI
+import XCTestDynamicOverlay
 import XXMessengerClient
+import XXModels
 
 public struct RegisterState: Equatable {
   public enum Field: String, Hashable {
@@ -33,15 +36,21 @@ public enum RegisterAction: Equatable, BindableAction {
 public struct RegisterEnvironment {
   public init(
     messenger: Messenger,
+    db: DBManagerGetDB,
+    now: @escaping () -> Date,
     mainQueue: AnySchedulerOf<DispatchQueue>,
     bgQueue: AnySchedulerOf<DispatchQueue>
   ) {
     self.messenger = messenger
+    self.db = db
+    self.now = now
     self.mainQueue = mainQueue
     self.bgQueue = bgQueue
   }
 
   public var messenger: Messenger
+  public var db: DBManagerGetDB
+  public var now: () -> Date
   public var mainQueue: AnySchedulerOf<DispatchQueue>
   public var bgQueue: AnySchedulerOf<DispatchQueue>
 }
@@ -49,6 +58,8 @@ public struct RegisterEnvironment {
 extension RegisterEnvironment {
   public static let unimplemented = RegisterEnvironment(
     messenger: .unimplemented,
+    db: .unimplemented,
+    now: XCTUnimplemented("\(Self.self).now"),
     mainQueue: .unimplemented,
     bgQueue: .unimplemented
   )
@@ -66,7 +77,15 @@ public let registerReducer = Reducer<RegisterState, RegisterAction, RegisterEnvi
     state.failure = nil
     return .future { [username = state.username] fulfill in
       do {
+        let db = try env.db()
         try env.messenger.register(username: username)
+        let contact = env.messenger.e2e()!.getContact()
+        try db.saveContact(Contact(
+          id: try contact.getId(),
+          marshaled: contact.data,
+          username: username,
+          createdAt: env.now()
+        ))
         fulfill(.success(.finished))
       }
       catch {
diff --git a/Examples/xx-messenger/Sources/RegisterFeature/RegisterView.swift b/Examples/xx-messenger/Sources/RegisterFeature/RegisterView.swift
index 27bc0962780d7214095ff26592d66c9f6703ae52..195b655b4806b3156a4fe4353fb4cd2ec708c51b 100644
--- a/Examples/xx-messenger/Sources/RegisterFeature/RegisterView.swift
+++ b/Examples/xx-messenger/Sources/RegisterFeature/RegisterView.swift
@@ -46,14 +46,12 @@ public struct RegisterView: View {
               viewStore.send(.registerTapped)
             } label: {
               HStack {
+                Text("Register")
+                Spacer()
                 if viewStore.isRegistering {
-                  ProgressView().padding(.trailing)
-                  Text("Registering...")
-                } else {
-                  Text("Register")
+                  ProgressView()
                 }
               }
-              .frame(maxWidth: .infinity)
             }
           }
 
diff --git a/Examples/xx-messenger/Sources/WelcomeFeature/WelcomeView.swift b/Examples/xx-messenger/Sources/WelcomeFeature/WelcomeView.swift
index d3686c5aa5f1b410cea89176feecdcf050dccb3a..1205c67eece34b9214ce16b3eb6e22df93d37c4b 100644
--- a/Examples/xx-messenger/Sources/WelcomeFeature/WelcomeView.swift
+++ b/Examples/xx-messenger/Sources/WelcomeFeature/WelcomeView.swift
@@ -29,21 +29,18 @@ public struct WelcomeView: View {
               viewStore.send(.newAccountTapped)
             } label: {
               HStack {
+                Text("New Account")
+                Spacer()
                 if viewStore.isCreatingAccount {
-                  ProgressView().padding(.trailing)
-                  Text("Creating Account...")
-                } else {
-                  Text("New Account")
+                  ProgressView()
                 }
               }
-              .frame(maxWidth: .infinity)
             }
 
             Button {
               viewStore.send(.restoreTapped)
             } label: {
               Text("Restore from Backup")
-                .frame(maxWidth: .infinity)
             }
           }
         }
diff --git a/Examples/xx-messenger/Tests/AppFeatureTests/AppFeatureTests.swift b/Examples/xx-messenger/Tests/AppFeatureTests/AppFeatureTests.swift
index 5f0554922106e525c5f6c151c958b602dd8f5552..5ea968131af6851815f66f6b22edf2d2d139dc56 100644
--- a/Examples/xx-messenger/Tests/AppFeatureTests/AppFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/AppFeatureTests/AppFeatureTests.swift
@@ -141,6 +141,36 @@ final class AppFeatureTests: XCTestCase {
     }
   }
 
+  func testHomeDidDeleteAccount() {
+    let store = TestStore(
+      initialState: AppState(
+        screen: .home(HomeState())
+      ),
+      reducer: appReducer,
+      environment: .unimplemented
+    )
+
+    let mainQueue = DispatchQueue.test
+    let bgQueue = DispatchQueue.test
+
+    store.environment.mainQueue = mainQueue.eraseToAnyScheduler()
+    store.environment.bgQueue = bgQueue.eraseToAnyScheduler()
+    store.environment.dbManager.hasDB.run = { true }
+    store.environment.messenger.isLoaded.run = { false }
+    store.environment.messenger.isCreated.run = { false }
+
+    store.send(.home(.didDeleteAccount)) {
+      $0.screen = .loading
+    }
+
+    bgQueue.advance()
+    mainQueue.advance()
+
+    store.receive(.set(\.$screen, .welcome(WelcomeState()))) {
+      $0.screen = .welcome(WelcomeState())
+    }
+  }
+
   func testWelcomeRestoreTapped() {
     let store = TestStore(
       initialState: AppState(
diff --git a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
index efdd867ff247317e7dd6dc379f38edfbc5ba7b3b..4fbad5b8c8a3d7775391db66359bd3c97f268ded 100644
--- a/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/HomeFeatureTests/HomeFeatureTests.swift
@@ -3,6 +3,7 @@ import RegisterFeature
 import XCTest
 import XXClient
 import XXMessengerClient
+import XXModels
 @testable import HomeFeature
 
 final class HomeFeatureTests: XCTestCase {
@@ -47,7 +48,6 @@ final class HomeFeatureTests: XCTestCase {
       environment: .unimplemented
     )
 
-    let username = "test_username"
     let bgQueue = DispatchQueue.test
     let mainQueue = DispatchQueue.test
     var messengerDidStartWithTimeout: [Int] = []
@@ -62,15 +62,6 @@ final class HomeFeatureTests: XCTestCase {
     store.environment.messenger.isLoggedIn.run = { false }
     store.environment.messenger.isRegistered.run = { true }
     store.environment.messenger.logIn.run = { messengerDidLogIn += 1 }
-    store.environment.messenger.e2e.get = {
-      var e2e = E2E.unimplemented
-      e2e.getContact.run = {
-        var contact = Contact.unimplemented(Data())
-        contact.getFactsFromContact.run = { _ in [Fact(fact: username, type: 0)] }
-        return contact
-      }
-      return e2e
-    }
 
     store.send(.start)
 
@@ -81,10 +72,6 @@ final class HomeFeatureTests: XCTestCase {
     XCTAssertNoDifference(messengerDidLogIn, 1)
 
     mainQueue.advance()
-
-    store.receive(.set(\.$username, username)) {
-      $0.username = username
-    }
   }
 
   func testRegisterFinished() {
@@ -96,7 +83,6 @@ final class HomeFeatureTests: XCTestCase {
       environment: .unimplemented
     )
 
-    let username = "test_username"
     let bgQueue = DispatchQueue.test
     let mainQueue = DispatchQueue.test
     var messengerDidStartWithTimeout: [Int] = []
@@ -109,15 +95,6 @@ final class HomeFeatureTests: XCTestCase {
     store.environment.messenger.isLoggedIn.run = { false }
     store.environment.messenger.isRegistered.run = { true }
     store.environment.messenger.logIn.run = { messengerDidLogIn += 1 }
-    store.environment.messenger.e2e.get = {
-      var e2e = E2E.unimplemented
-      e2e.getContact.run = {
-        var contact = Contact.unimplemented(Data())
-        contact.getFactsFromContact.run = { _ in [Fact(fact: username, type: 0)] }
-        return contact
-      }
-      return e2e
-    }
 
     store.send(.register(.finished)) {
       $0.register = nil
@@ -131,10 +108,6 @@ final class HomeFeatureTests: XCTestCase {
     XCTAssertNoDifference(messengerDidLogIn, 1)
 
     mainQueue.advance()
-
-    store.receive(.set(\.$username, username)) {
-      $0.username = username
-    }
   }
 
   func testStartMessengerStartFailure() {
@@ -229,4 +202,112 @@ final class HomeFeatureTests: XCTestCase {
       $0.failure = error.localizedDescription
     }
   }
+
+  func testAccountDeletion() {
+    let store = TestStore(
+      initialState: HomeState(),
+      reducer: homeReducer,
+      environment: .unimplemented
+    )
+
+    var dbDidFetchContacts: [XXModels.Contact.Query] = []
+    var udDidPermanentDeleteAccount: [Fact] = []
+    var messengerDidDestroy = 0
+    var dbDidDrop = 0
+
+    store.environment.bgQueue = .immediate
+    store.environment.mainQueue = .immediate
+    store.environment.messenger.e2e.get = {
+      var e2e: E2E = .unimplemented
+      e2e.getContact.run = {
+        var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
+        contact.getIdFromContact.run = { _ in "contact-id".data(using: .utf8)! }
+        return contact
+      }
+      return e2e
+    }
+    store.environment.db.run = {
+      var db: Database = .failing
+      db.fetchContacts.run = { query in
+        dbDidFetchContacts.append(query)
+        return [
+          XXModels.Contact(
+            id: "contact-id".data(using: .utf8)!,
+            marshaled: "contact-data".data(using: .utf8)!,
+            username: "MyUsername"
+          )
+        ]
+      }
+      db.drop.run = {
+        dbDidDrop += 1
+      }
+      return db
+    }
+    store.environment.messenger.ud.get = {
+      var ud: UserDiscovery = .unimplemented
+      ud.permanentDeleteAccount.run = { usernameFact in
+        udDidPermanentDeleteAccount.append(usernameFact)
+      }
+      return ud
+    }
+    store.environment.messenger.destroy.run = {
+      messengerDidDestroy += 1
+    }
+
+    store.send(.deleteAccountButtonTapped) {
+      $0.alert = .confirmAccountDeletion()
+    }
+
+    store.send(.set(\.$alert, nil)) {
+      $0.alert = nil
+    }
+
+    store.send(.deleteAccountConfirmed) {
+      $0.isDeletingAccount = true
+    }
+
+    XCTAssertNoDifference(dbDidFetchContacts, [.init(id: ["contact-id".data(using: .utf8)!])])
+    XCTAssertNoDifference(udDidPermanentDeleteAccount, [Fact(fact: "MyUsername", type: 0)])
+    XCTAssertNoDifference(messengerDidDestroy, 1)
+    XCTAssertNoDifference(dbDidDrop, 1)
+
+    store.receive(.didDeleteAccount) {
+      $0.isDeletingAccount = false
+    }
+  }
+
+  func testAccountDeletionFailure() {
+    let store = TestStore(
+      initialState: HomeState(),
+      reducer: homeReducer,
+      environment: .unimplemented
+    )
+
+    struct Failure: Error {}
+    let error = Failure()
+
+    store.environment.bgQueue = .immediate
+    store.environment.mainQueue = .immediate
+    store.environment.messenger.e2e.get = {
+      var e2e: E2E = .unimplemented
+      e2e.getContact.run = {
+        var contact = Contact.unimplemented("contact-data".data(using: .utf8)!)
+        contact.getIdFromContact.run = { _ in throw error }
+        return contact
+      }
+      return e2e
+    }
+
+    store.send(.deleteAccountConfirmed) {
+      $0.isDeletingAccount = true
+    }
+
+    store.receive(.set(\.$isDeletingAccount, false)) {
+      $0.isDeletingAccount = false
+    }
+
+    store.receive(.set(\.$alert, .accountDeletionFailed(error))) {
+      $0.alert = .accountDeletionFailed(error)
+    }
+  }
 }
diff --git a/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift b/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
index 21d4da16412ab852ff11e1b40da58ac1a5fd5388..a2aad5bd7977dbd210a163d8cdac9001de239723 100644
--- a/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
+++ b/Examples/xx-messenger/Tests/RegisterFeatureTests/RegisterFeatureTests.swift
@@ -1,8 +1,10 @@
 import ComposableArchitecture
 import XCTest
+import XXClient
+import XXMessengerClient
+import XXModels
 @testable import RegisterFeature
 
-@MainActor
 final class RegisterFeatureTests: XCTestCase {
   func testRegister() throws {
     let store = TestStore(
@@ -11,15 +13,35 @@ final class RegisterFeatureTests: XCTestCase {
       environment: .unimplemented
     )
 
+    let now = Date()
     let mainQueue = DispatchQueue.test
     let bgQueue = DispatchQueue.test
+    var dbDidSaveContact: [XXModels.Contact] = []
     var messengerDidRegisterUsername: [String] = []
 
+    store.environment.now = { now }
     store.environment.mainQueue = mainQueue.eraseToAnyScheduler()
     store.environment.bgQueue = bgQueue.eraseToAnyScheduler()
     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)! }
+        return contact
+      }
+      return e2e
+    }
+    store.environment.db.run = {
+      var db: Database = .failing
+      db.saveContact.run = { contact in
+        dbDidSaveContact.append(contact)
+        return contact
+      }
+      return db
+    }
 
     store.send(.set(\.$username, "NewUser")) {
       $0.username = "NewUser"
@@ -30,17 +52,56 @@ final class RegisterFeatureTests: XCTestCase {
     }
 
     XCTAssertNoDifference(messengerDidRegisterUsername, [])
+    XCTAssertNoDifference(dbDidSaveContact, [])
 
     bgQueue.advance()
 
     XCTAssertNoDifference(messengerDidRegisterUsername, ["NewUser"])
+    XCTAssertNoDifference(dbDidSaveContact, [
+      XXModels.Contact(
+        id: "contact-id".data(using: .utf8)!,
+        marshaled: "contact-data".data(using: .utf8)!,
+        username: "NewUser",
+        createdAt: now
+      )
+    ])
 
     mainQueue.advance()
 
     store.receive(.finished)
   }
 
-  func testRegisterFailure() throws {
+  func testGetDbFailure() throws {
+    struct Error: Swift.Error, Equatable {}
+    let error = Error()
+
+    let store = TestStore(
+      initialState: RegisterState(),
+      reducer: registerReducer,
+      environment: .unimplemented
+    )
+
+    let mainQueue = DispatchQueue.test
+    let bgQueue = DispatchQueue.test
+
+    store.environment.mainQueue = mainQueue.eraseToAnyScheduler()
+    store.environment.bgQueue = bgQueue.eraseToAnyScheduler()
+    store.environment.db.run = { throw error }
+
+    store.send(.registerTapped) {
+      $0.isRegistering = true
+    }
+
+    bgQueue.advance()
+    mainQueue.advance()
+
+    store.receive(.failed(error.localizedDescription)) {
+      $0.isRegistering = false
+      $0.failure = error.localizedDescription
+    }
+  }
+
+  func testMessengerRegisterFailure() throws {
     struct Error: Swift.Error, Equatable {}
     let error = Error()
 
@@ -55,6 +116,7 @@ final class RegisterFeatureTests: XCTestCase {
 
     store.environment.mainQueue = mainQueue.eraseToAnyScheduler()
     store.environment.bgQueue = bgQueue.eraseToAnyScheduler()
+    store.environment.db.run = { .failing }
     store.environment.messenger.register.run = { _ in throw error }
 
     store.send(.registerTapped) {
diff --git a/Sources/XXMessengerClient/Utils/Stored.swift b/Sources/XXMessengerClient/Utils/Stored.swift
index 3f5d5fdb186db87d79872f4ee44d3ad1cf799979..052d638705c6dce4a619fbe18d0d55cf2159733c 100644
--- a/Sources/XXMessengerClient/Utils/Stored.swift
+++ b/Sources/XXMessengerClient/Utils/Stored.swift
@@ -31,6 +31,23 @@ private final class Memory<Value> {
   var value: Value
 }
 
+extension Stored {
+  public struct MissingValueError: Error, Equatable {
+    public init(typeDescription: String) {
+      self.typeDescription = typeDescription
+    }
+
+    public var typeDescription: String
+  }
+
+  public func tryGet<T>() throws -> T where Value == Optional<T> {
+    guard let value = get() else {
+      throw MissingValueError(typeDescription: "\(Self.self)")
+    }
+    return value
+  }
+}
+
 extension Stored {
   public static func unimplemented(placeholder: Value) -> Stored<Value> {
     Stored<Value>(