diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index dedc124465b8022d9d3cf9008e20fe523a2d62ff..3b5efa05b8bd283b87c1670577d6e307124cad83 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -7,6 +7,7 @@
         <option name="testRunner" value="GRADLE" />
         <option name="distributionType" value="DEFAULT_WRAPPED" />
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleJvm" value="11" />
         <option name="modules">
           <set>
             <option value="$PROJECT_DIR$" />
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 2c2c251fdbbfef52f9769357417bcc468e0f3d6c..f743aa5b102586b6b100fde7f485ca1c59fa940d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -33,6 +33,9 @@ android {
 }
 
 dependencies {
+    implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
+    implementation((project(":cmix")))
+
     api(platform(project(":depconstraints")))
     kapt(platform(project(":depconstraints")))
     androidTestApi(platform(project(":depconstraints")))
@@ -43,7 +46,7 @@ dependencies {
 
     testImplementation(Libs.JUNIT)
     testImplementation(Libs.TRUTH)
-    
+
     androidTestImplementation(Libs.ESPRESSO_CORE)
     androidTestImplementation(Libs.EXT_JUNIT)
 }
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/DappModule.kt b/app/src/main/java/io/elixxir/dapp/DappModule.kt
new file mode 100644
index 0000000000000000000000000000000000000000..392a4e138c8801fd4a8fbcf560c172b3b14cbd24
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/DappModule.kt
@@ -0,0 +1,43 @@
+package io.elixxir.dapp
+
+import io.elixxir.dapp.android.model.AndroidConfig
+import io.elixxir.dapp.api.model.*
+import io.elixxir.dapp.logger.data.Logger
+import io.elixxir.dapp.api.model.CommonProperties
+import io.elixxir.dapp.api.model.DappConfig
+
+/**
+ * Singleton entry point to modules provided by the dApp SDK.
+ */
+class DappModule private constructor(
+    config: DappConfig,
+    logger: Logger = Logger.newInstance(config.loggerConfig)
+) : DappApi,
+    AndroidConfig by config.androidConfig,
+    Logger by logger,
+    CommonProperties
+{
+    override val accountApi: AccountApi
+        get() = TODO("Not yet implemented")
+    override val directoryApi: DirectoryApi
+        get() = TODO("Not yet implemented")
+    override val messagesApi: MessagesApi
+        get() = TODO("Not yet implemented")
+    override val networkApi: NetworkApi
+        get() = TODO("Not yet implemented")
+    override val requestsApi: RequestsApi
+        get() = TODO("Not yet implemented")
+    override val groupsApi: GroupsApi
+        get() = TODO("Not yet implemented")
+
+    companion object {
+        @Volatile
+        private var instance: DappModule? = null
+
+        fun getInstance(config: DappConfig): DappModule {
+            return instance ?: DappModule(config).apply {
+                instance = this
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/android/data/DefaultAndroidConfig.kt b/app/src/main/java/io/elixxir/dapp/android/data/DefaultAndroidConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..62a36d55c9c6ac48014a0bb470a8dc78b530ac2b
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/android/data/DefaultAndroidConfig.kt
@@ -0,0 +1,11 @@
+package io.elixxir.dapp.android.data
+
+import android.content.Context
+import io.elixxir.dapp.android.model.AndroidConfig
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+
+data class DefaultAndroidConfig(
+    override val context: () -> Context,
+    override val dispatcher: CoroutineDispatcher = Dispatchers.IO,
+) : AndroidConfig
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/android/model/AndroidConfig.kt b/app/src/main/java/io/elixxir/dapp/android/model/AndroidConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e31adddda82f68e0d92abac2931cf8587ff907f4
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/android/model/AndroidConfig.kt
@@ -0,0 +1,12 @@
+package io.elixxir.dapp.android.model
+
+import android.content.Context
+import kotlinx.coroutines.CoroutineDispatcher
+
+/**
+ * Android-specific properties used at runtime.
+ */
+interface AndroidConfig {
+    val context: () -> Context
+    val dispatcher: CoroutineDispatcher
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/data/AccountModule.kt b/app/src/main/java/io/elixxir/dapp/api/data/AccountModule.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b6e0c2ada41f78220bb78f7fe29ea30cf5e3acd0
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/data/AccountModule.kt
@@ -0,0 +1,42 @@
+package io.elixxir.dapp.api.data
+
+import io.elixxir.dapp.api.model.AccountApi
+import io.elixxir.dapp.backup.model.Backup
+import io.elixxir.dapp.session.repository.SessionDataSource
+import io.elixxir.dapp.user.model.User
+import io.elixxir.dapp.user.model.UserUpdateData
+import kotlinx.coroutines.*
+
+internal class AccountModule(
+    private val sessionManager: SessionDataSource
+) : AccountApi {
+    private val scope: CoroutineScope = CoroutineScope(
+        CoroutineName("AccountModule")
+                + Job()
+                + Dispatchers.Default
+    )
+
+    override fun getCurrentUser(): User {
+        TODO("Not yet implemented")
+    }
+
+    override fun createAccount(username: String) {
+        scope.launch {
+            sessionManager.createSession()
+        }
+    }
+
+    override fun restoreAccount(backup: Backup) {
+        TODO("Not yet implemented")
+    }
+
+    override fun updateAccount(updateData: UserUpdateData) {
+        TODO("Not yet implemented")
+    }
+
+    override fun deleteAccount() {
+        scope.launch {
+            sessionManager.deleteSession()
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/data/NetworkModule.kt b/app/src/main/java/io/elixxir/dapp/api/data/NetworkModule.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7a0e356035c5ffe383f84e43874074fc274b17f3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/data/NetworkModule.kt
@@ -0,0 +1,30 @@
+package io.elixxir.dapp.api.data
+
+import io.elixxir.dapp.api.model.NetworkApi
+import io.elixxir.dapp.network.model.ConnectionStatus
+import io.elixxir.dapp.network.data.NetworkManager
+import kotlinx.coroutines.CoroutineName
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
+
+internal class NetworkModule(
+    private val networkManager: NetworkManager
+) : NetworkApi {
+    private val scope: CoroutineScope = CoroutineScope(
+        CoroutineName("AccountModule")
+                + Job()
+                + Dispatchers.Default
+    )
+
+    override val connectionStatus: Flow<ConnectionStatus> by networkManager::connectionStatus
+
+    override fun connect(): Result<ConnectionStatus> {
+        TODO("Not yet implemented")
+    }
+
+    override fun disconnect(): Result<ConnectionStatus> {
+        TODO("Not yet implemented")
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/AccountApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/AccountApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8b231f83ef9ddeb4aefe7a63f7b9266d938f93e2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/AccountApi.kt
@@ -0,0 +1,13 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.backup.model.Backup
+import io.elixxir.dapp.user.model.User
+import io.elixxir.dapp.user.model.UserUpdateData
+
+interface AccountApi {
+    fun getCurrentUser(): User
+    fun createAccount(username: String)
+    fun restoreAccount(backup: Backup)
+    fun updateAccount(updateData: UserUpdateData)
+    fun deleteAccount()
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/CommonProperties.kt b/app/src/main/java/io/elixxir/dapp/api/model/CommonProperties.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ced9abdb6078976c3d4b926ced42177f47fbb6a4
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/CommonProperties.kt
@@ -0,0 +1,6 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.android.model.AndroidConfig
+import io.elixxir.dapp.logger.data.Logger
+
+internal interface CommonProperties : Logger, AndroidConfig
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/DappApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/DappApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e6998cad67d8104c89cf580211247446c419ebc8
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/DappApi.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.api.model
+
+interface DappApi {
+    val accountApi: AccountApi
+    val directoryApi: DirectoryApi
+    val messagesApi: MessagesApi
+    val networkApi: NetworkApi
+    val requestsApi: RequestsApi
+    val groupsApi: GroupsApi
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/DappConfig.kt b/app/src/main/java/io/elixxir/dapp/api/model/DappConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6b56f69920fb0acda678828b3e76e654f6004b46
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/DappConfig.kt
@@ -0,0 +1,15 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.android.model.AndroidConfig
+import io.elixxir.dapp.logger.model.LoggerConfig
+import io.elixxir.dapp.network.model.NetworkConfig
+
+/**
+ * Describes configurable options, and satisfies dependencies for,
+ * modules exposed by the dApps Kotlin SDK.
+ */
+interface DappConfig {
+    val androidConfig: AndroidConfig
+    val loggerConfig: LoggerConfig
+    val networkConfig: NetworkConfig
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/DirectoryApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/DirectoryApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6ff493985951db5c1b246c0e1d6ecdad4e079dcf
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/DirectoryApi.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.user.model.User
+import io.elixxir.dapp.user.model.UserQuery
+
+interface DirectoryApi {
+    fun getContacts(): List<User>
+    fun findUser(params: UserQuery): User?
+    fun blockUser(user: User)
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/GroupsApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/GroupsApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8cbccf2ab4afc5fa70f24307cbfdeef64ef5a5a7
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/GroupsApi.kt
@@ -0,0 +1,16 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.group.model.Group
+import io.elixxir.dapp.messaging.model.Message
+import io.elixxir.dapp.user.model.User
+import kotlinx.coroutines.flow.Flow
+
+interface GroupsApi {
+    val groupMessages: Flow<Message>
+    fun sendInvitation(group: Group)
+    fun resendInvitation(member: User)
+    fun joinGroup(group: Group)
+    fun leaveGroup(group: Group)
+    fun sendMessage(message: Message, group: Group)
+    fun retryMessage(message: Message, group: Group)
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/MessagesApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/MessagesApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0e7c76b6c46aefc635dc87eac9cbdcb462296cf3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/MessagesApi.kt
@@ -0,0 +1,11 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.messaging.model.Message
+import io.elixxir.dapp.user.model.User
+import kotlinx.coroutines.flow.Flow
+
+interface MessagesApi {
+    val messages: Flow<Message>
+    fun sendMessage(message: Message, recipient: User)
+    fun retryMessage(message: Message, recipient: User)
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/NetworkApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/NetworkApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7313681e02fa1b707a261648a85efbe5ff1545e2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/NetworkApi.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.network.model.ConnectionStatus
+import kotlinx.coroutines.flow.Flow
+
+interface NetworkApi {
+    val connectionStatus: Flow<ConnectionStatus>
+    fun connect(): Result<ConnectionStatus>
+    fun disconnect(): Result<ConnectionStatus>
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/RequestsApi.kt b/app/src/main/java/io/elixxir/dapp/api/model/RequestsApi.kt
new file mode 100644
index 0000000000000000000000000000000000000000..154bc8b86fe01b0ca7031e88ccb3224094b9ad47
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/RequestsApi.kt
@@ -0,0 +1,13 @@
+package io.elixxir.dapp.api.model
+
+import io.elixxir.dapp.request.model.IncomingRequest
+import io.elixxir.dapp.request.model.Request
+import io.elixxir.dapp.request.model.OutgoingRequest
+import kotlinx.coroutines.flow.Flow
+
+interface RequestsApi {
+    val requests: Flow<Request>
+    fun sendRequest(request: OutgoingRequest)
+    fun acceptRequest(request: IncomingRequest)
+    fun retryRequest(request: Request)
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/api/model/RetryStrategy.kt b/app/src/main/java/io/elixxir/dapp/api/model/RetryStrategy.kt
new file mode 100644
index 0000000000000000000000000000000000000000..91fa23967c74f6af58bf657c8aa01ba5257d03f4
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/api/model/RetryStrategy.kt
@@ -0,0 +1,16 @@
+package io.elixxir.dapp.api.model
+
+interface RetryStrategy {
+    val maxRetries: Int
+    val retryDelayMs: Long
+}
+
+/**
+ * Remote data that is critical to the function of the SDK.
+ * Generally means many retries and reasonable delay to not
+ * overwhelm network resources.
+ */
+data class CriticalRemoteDataStrategy(
+    override val maxRetries: Int = 29,
+    override val retryDelayMs: Long = 1000L
+) : RetryStrategy
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/backup/model/Backup.kt b/app/src/main/java/io/elixxir/dapp/backup/model/Backup.kt
new file mode 100644
index 0000000000000000000000000000000000000000..72bd8329420d7c2489fd5324f58cf9d1e776eb48
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/backup/model/Backup.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.backup.model
+
+interface Backup {
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/AuthEventListener.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/AuthEventListener.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4eca68a8c98c453bff18b1d3f8a00209e5f1d5a2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/AuthEventListener.kt
@@ -0,0 +1,14 @@
+package io.elixxir.dapp.bindings.data
+
+import bindings.AuthCallbacks
+
+interface AuthEventListener {
+    fun onConfirm(var1: ByteArray?, var2: ByteArray?, var3: Long, var5: Long)
+
+    fun onRequest(var1: ByteArray?, var2: ByteArray?, var3: Long, var5: Long)
+
+    fun onReset(var1: ByteArray?, var2: ByteArray?, var3: Long, var5: Long)
+}
+
+@JvmInline
+internal value class AuthCallbacksAdapter(val value: AuthCallbacks)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/Backup.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/Backup.kt
new file mode 100644
index 0000000000000000000000000000000000000000..547cebe85f6d67b8b96a3e2a9e0e1d9529b474d1
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/Backup.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.data
+
+internal interface Backup {
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/BackupAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/BackupAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2a3af5d63808070f60609eeb22f604cdfa429401
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/BackupAdapter.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.data
+
+@JvmInline
+internal value class BackupAdapter(val backup: bindings.Backup) : Backup
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/Bindings.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/Bindings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6083e320e48cde159bdaeae4d771a6ed8e98c677
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/Bindings.kt
@@ -0,0 +1,68 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.logger.model.LoggerConfig
+import io.elixxir.dapp.network.repository.Ndf
+import io.elixxir.dapp.session.model.SessionPassword
+
+internal interface Bindings {
+    val defaultE2eParams: E2eParams
+    val defaultCmixParams: CmixParams
+    val defaultFileTransferParams: FileTransferParams
+    val gitVersion: String
+
+    fun generateSecret(byteLength: Long): SessionPassword
+
+    fun loadCmix(
+        sessionFileDirectory: String,
+        sessionPassword: SessionPassword,
+        cmixParams: CmixParams
+    ): Cmix
+
+    fun login(
+        cmixId: CmixId,
+        authCallbacks: AuthCallbacksAdapter,
+        receptionIdentity: ReceptionIdentity,
+        e2eParams: E2eParams
+    ): E2e
+
+    fun getOrCreateUd(
+        e2eId: E2eId,
+        networkFollowerStatus: NetworkFollowerStatus,
+        username: String,
+        signature: RegistrationValidationSignature,
+        udCert: UdCertificate,
+        contact: Contact,
+        udIpAddress: UdIpAddress
+    ): UserDiscovery
+
+    fun newUdFromBackup(
+        e2eId: E2eId,
+        networkFollowerStatus: NetworkFollowerStatus,
+        emailFact: Fact,
+        phoneFact: Fact,
+        udCert: UdCertificate,
+        contact: Contact,
+        udAddress: UdIpAddress
+    ): UserDiscovery
+
+    fun newDummyTrafficManager(): DummyTrafficManager
+
+    fun registerLogger(loggerConfig: LoggerConfig)
+
+    fun initializeBackup(): Backup
+
+    fun resumeBackup(): Backup
+
+    fun fetchSignedNdf(
+        url: String,
+        cert: String
+    ): Ndf
+
+    fun getReceptionIdentity(
+        key: SessionPassword,
+        cmixId: CmixId
+    ): ReceptionIdentity
+}
+
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/BindingsAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/BindingsAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3cdfe670515414b94a50af68e78a97be7cd879b7
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/BindingsAdapter.kt
@@ -0,0 +1,140 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.bindings.model.ReceptionIdentity
+import io.elixxir.dapp.logger.model.LoggerConfig
+import io.elixxir.dapp.network.repository.Ndf
+import io.elixxir.dapp.session.model.SessionPassword
+import io.elixxir.dapp.util.toBase64String
+import bindings.Bindings as CoreBindings
+
+internal class BindingsAdapter: Bindings {
+    override val defaultE2eParams: E2eParams
+        get() = E2eParams(CoreBindings.getDefaultE2EParams())
+    override val defaultCmixParams: CmixParams
+        get() = CmixParams(CoreBindings.getDefaultCMixParams())
+    override val defaultFileTransferParams: FileTransferParams
+        get() = FileTransferParams(CoreBindings.getDefaultFileTransferParams())
+    override val gitVersion: String
+        get() = CoreBindings.getGitVersion()
+
+    override fun generateSecret(byteLength: Long): SessionPassword {
+        return SessionPassword(CoreBindings.generateSecret(byteLength))
+    }
+
+    override fun loadCmix(
+        sessionFileDirectory: String,
+        sessionPassword: SessionPassword,
+        cmixParams: CmixParams
+    ): Cmix {
+        return CmixAdapter(
+            CoreBindings.loadCmix(
+                sessionFileDirectory,
+                sessionPassword.value,
+                cmixParams.value
+            )
+        )
+    }
+
+    override fun login(
+        cmixId: CmixId,
+        authCallbacks: AuthCallbacksAdapter,
+        receptionIdentity: ReceptionIdentity,
+        e2eParams: E2eParams
+    ): E2e {
+        // TODO: Use factory method to get E2E implementation
+        return E2eAdapter(
+            CoreBindings.login(
+                cmixId.value,
+                authCallbacks.value,
+                receptionIdentity.value,
+                e2eParams.value
+            )
+        )
+    }
+
+    override fun getOrCreateUd(
+        e2eId: E2eId,
+        networkFollowerStatus: NetworkFollowerStatus,
+        username: String,
+        signature: RegistrationValidationSignature,
+        udCert: UdCertificate,
+        contact: Contact,
+        udIpAddress: UdIpAddress
+    ): UserDiscovery {
+        // TODO: Use factory method to get UD implementation
+        return UserDiscoveryAdapter(
+            CoreBindings.newOrLoadUd(
+                e2eId.value,
+                { networkFollowerStatus.code },
+                username,
+                signature.value,
+                udCert.value,
+                contact.value,
+                udIpAddress.value
+            )
+        )
+    }
+
+    override fun newUdFromBackup(
+        e2eId: E2eId,
+        networkFollowerStatus: NetworkFollowerStatus,
+        emailFact: Fact,
+        phoneFact: Fact,
+        udCert: UdCertificate,
+        contact: Contact,
+        udIpAddress: UdIpAddress
+    ): UserDiscovery {
+        // TODO: Use factory method to get UD implementation
+        return UserDiscoveryAdapter(
+            CoreBindings.newUdManagerFromBackup(
+                e2eId.value,
+                { networkFollowerStatus.code },
+                emailFact.value,
+                phoneFact.value,
+                udCert.value,
+                contact.value,
+                udIpAddress.value
+            )
+        )
+    }
+
+    override fun newDummyTrafficManager(): DummyTrafficManager {
+        TODO("Not yet implemented")
+    }
+
+    override fun registerLogger(loggerConfig: LoggerConfig) {
+        with (loggerConfig) {
+            CoreBindings.logLevel(logLevel.code)
+            CoreBindings.registerLogWriter(logWriter)
+        }
+    }
+
+    override fun initializeBackup(): Backup {
+        TODO("Not yet implemented")
+    }
+
+    override fun resumeBackup(): Backup {
+        TODO("Not yet implemented")
+    }
+
+    override fun fetchSignedNdf(
+        url: String,
+        cert: String
+    ): Ndf {
+        return CoreBindings.downloadAndVerifySignedNdfWithUrl(url, cert).toBase64String()
+    }
+
+    override fun getReceptionIdentity(
+        key: SessionPassword,
+        cmixId: CmixId
+    ): ReceptionIdentity {
+        return ReceptionIdentity(
+            CoreBindings.loadReceptionIdentity(
+                key.value.toBase64String(),
+                cmixId.value
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/Cmix.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/Cmix.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ef91c1f5b20cf25aeb691f2a3826d611cb664be9
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/Cmix.kt
@@ -0,0 +1,31 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.Contact
+import io.elixxir.dapp.bindings.model.E2eId
+import io.elixxir.dapp.bindings.model.NetworkFollowerStatus
+
+internal interface Cmix {
+    fun connect(
+        e2eId: E2eId,
+        recipientContact: Contact,
+        e2eParams: E2eParams
+    ): Connection
+
+    fun startNetworkFollower(timeoutMs: Long)
+
+    fun stopNetworkFollower()
+
+    fun isNetworkHealthy(): Boolean
+
+    fun registerHealthListener(listener: NetworkHealthListener): HealthListenerId
+
+    fun unregisterHealthListener(id: HealthListenerId)
+
+    fun getNodeRegistrationStatus(): NodeRegistrationStatus
+
+    fun makeReceptionIdentity(): ReceptionIdentity
+
+    fun getNetworkFollowerStatus(): NetworkFollowerStatus
+}
+
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/CmixAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/CmixAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7c7203b420eee201f6b19c9062adf296b788f253
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/CmixAdapter.kt
@@ -0,0 +1,62 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.Connection
+import io.elixxir.dapp.bindings.model.Contact
+import io.elixxir.dapp.bindings.model.E2eId
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.bindings.model.NetworkFollowerStatus
+import bindings.Cmix as CoreCmix
+
+@JvmInline
+internal value class CmixAdapter(private val cmix: CoreCmix) : Cmix {
+
+    override fun connect(
+        e2eId: E2eId,
+        recipientContact: Contact,
+        e2eParams: E2eParams
+    ): Connection {
+        // TODO: Use factory method to get Connection implementation
+        return ConnectionAdapter(
+            cmix.connect(
+                e2eId.value,
+                recipientContact.value,
+                e2eParams.value
+            )
+        )
+    }
+
+    override fun startNetworkFollower(timeoutMs: Long) {
+        cmix.startNetworkFollower(timeoutMs)
+    }
+
+    override fun stopNetworkFollower() {
+        cmix.stopNetworkFollower()
+    }
+
+    override fun isNetworkHealthy(): Boolean {
+        return cmix.isHealthy
+    }
+
+    override fun registerHealthListener(listener: NetworkHealthListener): HealthListenerId {
+        return HealthListenerId(
+            cmix.addHealthCallback(HealthCallbackAdapter.placeholder)
+        )
+    }
+
+    override fun unregisterHealthListener(id: HealthListenerId) {
+        cmix.removeHealthCallback(id.value)
+    }
+
+    override fun getNodeRegistrationStatus(): NodeRegistrationStatus {
+        return NodeRegistrationStatus(cmix.nodeRegistrationStatus)
+    }
+
+    override fun makeReceptionIdentity(): ReceptionIdentity {
+        return ReceptionIdentity(cmix.makeReceptionIdentity())
+    }
+
+    override fun getNetworkFollowerStatus(): NetworkFollowerStatus {
+        return NetworkFollowerStatus.from(cmix.networkFollowerStatus())
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/DummyTrafficManager.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/DummyTrafficManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4939e23eafb11a2ecfdbc0cef9f848f02b735392
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/DummyTrafficManager.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.data
+
+interface DummyTrafficManager {
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/E2e.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/E2e.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ce271d3af252c4e1e45d76a9b8edae8c2d85ceed
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/E2e.kt
@@ -0,0 +1,49 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.bindings.model.ReceptionIdentity
+import io.elixxir.dapp.user.model.UserId
+
+internal interface E2e {
+    val payloadSize: Long
+
+    fun getReceptionId(): ReceptionIdentity
+    fun getContact(): Contact
+    fun callAllReceivedRequests()
+    fun confirmRequest(userId: UserId)
+    fun deleteAllRequests()
+    fun deleteRequest(request: Request)
+    fun deleteSentRequests()
+
+    fun getAllPartnerIds(): PartnersList
+
+    fun hasAuthenticatedChannel(contact: Contact): Boolean
+
+    fun registerListener(
+        senderId: UserId,
+        messageType: MessageType,
+        e2eListener: E2eListener
+    )
+
+    fun reset(contact: Contact): RoundId
+
+    fun sendRequest(
+        contact: Contact,
+        myFactsList: FactsList
+    ): RoundId
+
+    fun verifyOwnership(
+        receivedUserId: UserId,
+        verifiedContact: Contact,
+        e2eHandler: E2eHandler
+    ): Boolean
+
+    fun sendE2e(
+        messageType: MessageType,
+        receiverId: UserId,
+        payload: Payload,
+        params: E2eParams
+    ): SendReport
+}
+
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/E2eAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/E2eAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..588f8e95c68c54335da1ea389459fa8cab67f9e6
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/E2eAdapter.kt
@@ -0,0 +1,104 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.bindings.model.ReceptionIdentity
+import bindings.E2e as CoreE2e
+import io.elixxir.dapp.user.model.UserId
+
+@JvmInline
+internal value class E2eAdapter(private val e2e: CoreE2e) : E2e {
+    override val payloadSize: Long
+        get() = e2e.payloadSize()
+
+    override fun getReceptionId(): ReceptionIdentity {
+        return ReceptionIdentity(e2e.receptionID)
+    }
+
+    override fun getContact(): Contact {
+        return Contact(e2e.contact)
+    }
+
+    override fun callAllReceivedRequests() {
+        e2e.callAllReceivedRequests()
+    }
+
+    override fun confirmRequest(userId: UserId) {
+        e2e.confirm(userId.value)
+    }
+
+    override fun deleteAllRequests() {
+        e2e.deleteAllRequests()
+    }
+
+    override fun deleteRequest(request: Request) {
+        e2e.deleteRequest(request.value)
+    }
+
+    override fun deleteSentRequests() {
+        e2e.deleteSentRequests()
+    }
+
+    override fun getAllPartnerIds(): PartnersList {
+        return PartnersList(e2e.allPartnerIDs)
+    }
+
+    override fun hasAuthenticatedChannel(contact: Contact): Boolean {
+        return e2e.hasAuthenticatedChannel(contact.value)
+    }
+
+    override fun registerListener(
+        senderId: UserId,
+        messageType: MessageType,
+        e2eListener: E2eListener
+    ) {
+        e2e.registerListener(
+            senderId.value,
+            messageType.code,
+            e2eListener
+        )
+    }
+
+    override fun reset(contact: Contact): RoundId {
+        return RoundId(
+            e2e.reset(contact.value)
+        )
+    }
+
+    override fun sendRequest(
+        contact: Contact,
+        myFactsList: FactsList
+    ): RoundId {
+        return RoundId(
+            e2e.request(contact.value, myFactsList.value)
+        )
+    }
+
+    override fun verifyOwnership(
+        receivedUserId: UserId,
+        verifiedContact: Contact,
+        e2eHandler: E2eHandler
+    ): Boolean {
+        return e2e.verifyOwnership(
+            receivedUserId.value,
+            verifiedContact.value,
+            e2eHandler.value
+        )
+    }
+
+    override fun sendE2e(
+        messageType: MessageType,
+        receiverId: UserId,
+        payload: Payload,
+        params: E2eParams
+    ): SendReport {
+        return SendReport(
+            e2e.sendE2E(
+                messageType.code,
+                receiverId.value,
+                payload.value,
+                params.value
+            )
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChat.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChat.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ff2d4d85dc13963b169eca4d310649f2f3daa343
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChat.kt
@@ -0,0 +1,14 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.GroupInfo
+import io.elixxir.dapp.bindings.model.GroupReport
+import io.elixxir.dapp.group.model.Group
+import io.elixxir.dapp.group.model.GroupId
+
+internal interface GroupChat {
+    fun getGroup(groupId: GroupId): Group
+    fun joinGroup(trackedGroupId: Long)
+    fun leaveGroup(groupId: GroupId)
+    fun makeGroup(info: GroupInfo): GroupReport
+    fun resendInvitations(group: Group): GroupReport
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChatAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChatAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..277bc79934ddb01b67f6d5fcafd91a4b67483845
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/GroupChatAdapter.kt
@@ -0,0 +1,37 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.GroupAdapter
+import io.elixxir.dapp.bindings.model.GroupInfo
+import io.elixxir.dapp.bindings.model.GroupReport
+import io.elixxir.dapp.group.model.Group
+import io.elixxir.dapp.group.model.GroupId
+import bindings.GroupChat as CoreGroupChat
+
+internal class GroupChatAdapter(private val groupChat: CoreGroupChat) : GroupChat {
+    override fun getGroup(groupId: GroupId): Group {
+         return GroupAdapter(groupChat.getGroup(groupId.value))
+    }
+
+    override fun joinGroup(trackedGroupId: Long) {
+        groupChat.joinGroup(trackedGroupId)
+    }
+
+    override fun leaveGroup(groupId: GroupId) {
+        groupChat.leaveGroup(groupId.value)
+    }
+
+    override fun makeGroup(info: GroupInfo): GroupReport {
+        return GroupReport(
+            groupChat.makeGroup(
+                info.membershipData.value,
+                info.description.toByteArray(),
+                info.name.toByteArray())
+        )
+    }
+
+    override fun resendInvitations(group: Group): GroupReport {
+        return GroupReport(
+            groupChat.resendRequest(group.groupId.value)
+        )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/UdListener.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/UdListener.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5a5132de556ea0fca521f2d32b9921922e29a81d
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/UdListener.kt
@@ -0,0 +1,35 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.Contact
+
+internal interface UdListener {
+    val onComplete: (Contact?, Exception?) -> Unit
+}
+
+internal class UdSearchResultListener(
+    private val listener: UdListener
+) : bindings.UdSearchCallback,
+    bindings.UdLookupCallback,
+    UdListener by listener
+{
+
+    override fun callback(
+        contactData: ByteArray?,
+        error: java.lang.Exception?
+    ) {
+        onComplete(
+            Contact(contactData ?: byteArrayOf()),
+            error
+        )
+    }
+
+    companion object {
+        val placeholder: UdSearchResultListener =
+            UdSearchResultListener(
+                object : UdListener {
+                    override val onComplete: (Contact?, Exception?) -> Unit
+                            = { _, _, -> }
+                }
+            )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscovery.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscovery.kt
new file mode 100644
index 0000000000000000000000000000000000000000..124a9bb25130f0e64f3d1bc8cc1f5a60a85a5138
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscovery.kt
@@ -0,0 +1,38 @@
+package io.elixxir.dapp.bindings.data
+
+import io.elixxir.dapp.bindings.model.ConfirmationCode
+import io.elixxir.dapp.bindings.model.ConfirmationId
+import io.elixxir.dapp.bindings.model.Contact
+import io.elixxir.dapp.bindings.model.FactsList
+import io.elixxir.dapp.user.model.UserId
+
+internal interface UserDiscovery {
+    fun getContact(): Contact
+
+    fun getFacts(): FactsList
+
+    fun registerUsername(username: String)
+
+    fun registerEmail(email: String): ConfirmationId
+
+    fun registerPhone(phone: String): ConfirmationId
+
+    fun confirmTwoFactorAuth(
+        confirmationId: ConfirmationId,
+        confirmationCode: ConfirmationCode
+    )
+
+    fun removeEmail()
+
+    fun removePhone()
+
+    fun deleteUser()
+
+    fun findUserById(userId: UserId): Result<Contact>
+
+    fun usernameSearch(username: String): Result<Contact>
+
+    fun phoneSearch(phone: String): Result<Contact>
+
+    fun emailSearch(email: String): Result<Contact>
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscoveryAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscoveryAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9b1161b1a18f3c94af299ef92649e38d98006382
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/data/UserDiscoveryAdapter.kt
@@ -0,0 +1,103 @@
+package io.elixxir.dapp.bindings.data
+
+import bindings.Bindings
+import io.elixxir.dapp.bindings.model.*
+import io.elixxir.dapp.bindings.model.Contact
+import io.elixxir.dapp.bindings.model.Fact
+import io.elixxir.dapp.bindings.model.FactsList
+import io.elixxir.dapp.user.model.UserId
+import bindings.UserDiscovery as CoreUserDiscovery
+
+@JvmInline
+internal value class UserDiscoveryAdapter(private val ud: CoreUserDiscovery) : UserDiscovery {
+
+    override fun getContact(): Contact {
+        return Contact(ud.contact)
+    }
+
+    override fun getFacts(): FactsList {
+        return FactsList(ud.facts)
+    }
+
+    override fun registerUsername(username: String) {
+        TODO("Not yet implemented")
+    }
+
+    override fun registerEmail(email: String): ConfirmationId{
+        return ConfirmationId(
+            ud.sendRegisterFact(Fact.placeholder)
+        )
+    }
+
+    override fun registerPhone(phone: String): ConfirmationId {
+        return ConfirmationId(
+            ud.sendRegisterFact(Fact.placeholder)
+        )
+    }
+
+    override fun confirmTwoFactorAuth(
+        confirmationId: ConfirmationId,
+        confirmationCode: ConfirmationCode
+    ) {
+        ud.confirmFact(
+            confirmationId.value,
+            confirmationCode.value
+        )
+    }
+
+    override fun removeEmail() {
+        ud.removeFact(Fact.placeholder)
+    }
+
+    override fun removePhone() {
+        ud.removeFact(Fact.placeholder)
+    }
+
+    override fun deleteUser() {
+        ud.permanentDeleteAccount(ud.contact)
+    }
+
+    override fun findUserById(userId: UserId): Result<Contact> {
+        Bindings.lookupUD(
+            E2eId.placeholder,
+            userId.value,
+            UdSearchResultListener.placeholder,
+            LookupId.placeholder,
+            SearchParams.placeholder
+        )
+        return Result.success(Contact(byteArrayOf()))
+    }
+
+    override fun usernameSearch(username: String): Result<Contact> {
+        Bindings.searchUD(
+            E2eId.placeholder,
+            Contact.placeholder,
+            UdSearchResultListener.placeholder,
+            FactsList.placeholder,
+            SearchParams.placeholder,
+        )
+        return Result.success(Contact(byteArrayOf()))
+    }
+
+    override fun phoneSearch(phone: String): Result<Contact> {
+        Bindings.searchUD(
+            E2eId.placeholder,
+            Contact.placeholder,
+            UdSearchResultListener.placeholder,
+            FactsList.placeholder,
+            SearchParams.placeholder,
+        )
+        return Result.success(Contact(byteArrayOf()))
+    }
+
+    override fun emailSearch(email: String): Result<Contact> {
+        Bindings.searchUD(
+            E2eId.placeholder,
+            Contact.placeholder,
+            UdSearchResultListener.placeholder,
+            FactsList.placeholder,
+            SearchParams.placeholder,
+        )
+        return Result.success(Contact(byteArrayOf()))
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/AuthenticatedConnection.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/AuthenticatedConnection.kt
new file mode 100644
index 0000000000000000000000000000000000000000..72b5c6ae5e9791c035fa9e11b4260836416aa066
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/AuthenticatedConnection.kt
@@ -0,0 +1,5 @@
+package io.elixxir.dapp.bindings.model
+
+internal interface AuthenticatedConnection : Connection {
+    fun isAuthenticated()
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/CmixId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/CmixId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4978a8f2da2e36bf6d08590829bed89fd01248a0
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/CmixId.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class CmixId(val value: Long) {
+
+    companion object {
+        val placeholder: Long = 0
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/CmixParams.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/CmixParams.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9667fd5b108437f3b42c14ba256694d1149ce8a0
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/CmixParams.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class CmixParams(val value: ByteArray) {
+
+    companion object {
+        val placeholder = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationCode.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationCode.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1ba08f6e9674a1fe1d074cd0f29cfa636f9314e3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationCode.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class ConfirmationCode(val value: String)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dee10cb12ab517d2de7313bb00202fd811c09186
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/ConfirmationId.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class ConfirmationId(val value: String)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/Connection.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/Connection.kt
new file mode 100644
index 0000000000000000000000000000000000000000..de4edff39b2bd0a1bf8d9ee45fc690c3da892e77
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/Connection.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+internal interface Connection {
+    fun getId(): Long
+    fun getPartner(): ByteArray
+    fun registerListener()
+    fun sendE2e()
+    fun close()
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/ConnectionAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/ConnectionAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..28342c5b161a910f20dd4e1ac89d43662f180f3b
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/ConnectionAdapter.kt
@@ -0,0 +1,26 @@
+package io.elixxir.dapp.bindings.model
+
+import bindings.Connection as CoreConnection
+
+@JvmInline
+value class ConnectionAdapter(private val connection: CoreConnection) : Connection {
+    override fun getId(): Long {
+        TODO("Not yet implemented")
+    }
+
+    override fun getPartner(): ByteArray {
+        TODO("Not yet implemented")
+    }
+
+    override fun registerListener() {
+        TODO("Not yet implemented")
+    }
+
+    override fun sendE2e() {
+        TODO("Not yet implemented")
+    }
+
+    override fun close() {
+        TODO("Not yet implemented")
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/Contact.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/Contact.kt
new file mode 100644
index 0000000000000000000000000000000000000000..86b5a5c6e978ba3d028bde03d307e5edfa48fac3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/Contact.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class Contact(val value: ByteArray) {
+
+    companion object {
+        val placeholder: ByteArray = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/E2eHandler.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c184ee9a20eb07a1dea3bcf49099191fc1fb540f
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eHandler.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class E2eHandler(val value: Long)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/E2eId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2810ce3867490c0a0aad4f41086f0bb684237fe1
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eId.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class E2eId(val value: Long) {
+
+    companion object {
+        val placeholder: Long = 0
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/E2eListener.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eListener.kt
new file mode 100644
index 0000000000000000000000000000000000000000..07f58d8c6cd8fbb571f56da39d57f1269fea8254
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eListener.kt
@@ -0,0 +1,5 @@
+package io.elixxir.dapp.bindings.model
+
+import bindings.Listener
+
+internal interface E2eListener : Listener
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/E2eParams.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eParams.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cd0fc1c3f6bffe109eb57f7c2fc1328691fdb7b3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/E2eParams.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class E2eParams(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/Fact.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/Fact.kt
new file mode 100644
index 0000000000000000000000000000000000000000..86b9b915f506d762c0cc7c254a7025b33e9784ab
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/Fact.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class Fact(val value: ByteArray) {
+
+    companion object {
+        val placeholder: ByteArray = Fact(byteArrayOf()).value
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/FactsList.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/FactsList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fa3a49c24bc4a1e79f9885f26ddbb2528b08e5c9
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/FactsList.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class FactsList(val value: ByteArray) {
+
+    companion object {
+        val placeholder: ByteArray = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/FileTransferParams.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/FileTransferParams.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fc7cf4d6ebab8f04b69400d980eea505dbe3583e
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/FileTransferParams.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class FileTransferParams(val value: ByteArray) {
+
+    companion object {
+        val plaeholder = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/GroupAdapter.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..07a97a7dd461756db4966f651cd4f6e2f5ed3908
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupAdapter.kt
@@ -0,0 +1,20 @@
+package io.elixxir.dapp.bindings.model
+
+import io.elixxir.dapp.group.model.Group
+import io.elixxir.dapp.group.model.GroupId
+import io.elixxir.dapp.user.model.User
+import bindings.Group as CoreGroup
+
+@JvmInline
+internal value class GroupAdapter(val value: CoreGroup): Group {
+    override val groupId: GroupId
+        get() = GroupId(value.id)
+    override val name: String
+        get() = String(value.name)
+    override val description: String
+        get() = String(value.initMessage)
+    override val members: List<User>
+        get() = listOf()
+    override val creator: User
+        get() = User.placeholder
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/GroupInfo.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupInfo.kt
new file mode 100644
index 0000000000000000000000000000000000000000..84b84ddc462d0d106fa3540432617f7529acdae0
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupInfo.kt
@@ -0,0 +1,7 @@
+package io.elixxir.dapp.bindings.model
+
+internal data class GroupInfo(
+    val membershipData: GroupMembership,
+    val description: String,
+    val name: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/GroupMembership.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupMembership.kt
new file mode 100644
index 0000000000000000000000000000000000000000..04c32bf12a8c43c125e569625d0256a9e3c00238
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupMembership.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class GroupMembership(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/GroupReport.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupReport.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c70edbb833711757ee5d25fbcb4cec8cef6abc2c
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/GroupReport.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class GroupReport(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/HealthCallback.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/HealthCallback.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bc5aec42b9d98577f51da4b26cdc19228eaac4d3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/HealthCallback.kt
@@ -0,0 +1,24 @@
+package io.elixxir.dapp.bindings.model
+
+internal interface NetworkHealthListener {
+    fun onHealthChanged(isHealthy: Boolean)
+}
+
+internal class HealthCallbackAdapter(
+    private val listener: NetworkHealthListener
+) : NetworkHealthListener by listener,
+    bindings.NetworkHealthCallback
+{
+    override fun callback(isHealthy: Boolean) {
+        onHealthChanged(isHealthy)
+    }
+
+    companion object {
+        val placeholder: HealthCallbackAdapter =
+            HealthCallbackAdapter(
+                object : NetworkHealthListener {
+                    override fun onHealthChanged(isHealthy: Boolean) { }
+                }
+            )
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/HealthListenerId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/HealthListenerId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5034d6810b296e4fb05643409eb1b3c8fafc07c9
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/HealthListenerId.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class HealthListenerId(val value: Long)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/LookupId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/LookupId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..928bf0491d37544a3550318cfabdf704126824cb
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/LookupId.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class LookupId(val value: ByteArray) {
+
+    companion object {
+        val placeholder: ByteArray = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/MessageType.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/MessageType.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c72785377958e613dba8694708ffaf9a796d0c03
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/MessageType.kt
@@ -0,0 +1,23 @@
+package io.elixxir.dapp.bindings.model
+
+internal enum class MessageType(val code: Long) {
+    NoType(0),
+    XxMessage(2),
+    KeyExchangeTrigger(30),
+    KeyExchangeConfirm(31),
+    KeyExchangeTriggerEphemeral(32),
+    KeyExchangeConfirmEphemeral(33),
+    E2eClose(34),
+    GroupCreationRequest(40),
+    NewFileTransfer(50),
+    EndFileTransfer(51),
+    ConnectionAuthenticationRequest(60);
+
+    companion object {
+        fun from(code: Long): MessageType {
+            return values().firstOrNull {
+                it.code == code
+            } ?: throw(IllegalArgumentException("Invalid code"))
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/NetworkFollowerStatus.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/NetworkFollowerStatus.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fdc5058d5782df2f9c14a203dc6a379f5afb4f04
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/NetworkFollowerStatus.kt
@@ -0,0 +1,12 @@
+package io.elixxir.dapp.bindings.model
+
+internal enum class NetworkFollowerStatus(val code: Long) {
+    STOPPED(0),
+    STARTING(1000),
+    RUNNING(2000),
+    STOPPING(3000);
+
+    companion object {
+        fun from(code: Long) = values().first { it.code == code }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/NodeRegistrationStatus.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/NodeRegistrationStatus.kt
new file mode 100644
index 0000000000000000000000000000000000000000..620eee54a3914d7de4577827aa5882f7f6a01ee7
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/NodeRegistrationStatus.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class NodeRegistrationStatus(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/PartnersList.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/PartnersList.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c040838a3ecf90d655185b1fb5205a54891501b2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/PartnersList.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class PartnersList(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/Payload.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/Payload.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1901047bd5ceb496bcbf16374a8bd8bdd85206f6
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/Payload.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class Payload(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/ReceptionIdentity.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/ReceptionIdentity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..313a564aaf07e932da7ea052cb3160e3f8a2dc1e
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/ReceptionIdentity.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class ReceptionIdentity(val value: ByteArray)
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/RegistrationValidationSignature.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/RegistrationValidationSignature.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5609b0185dfde3ba9dca9cd3e96a0101f9ed340b
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/RegistrationValidationSignature.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class RegistrationValidationSignature(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/Request.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/Request.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1bc8a67e0c28e17f69407d63bc174316f992dc1
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/Request.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class Request(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/RoundId.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/RoundId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e88ff523684c705974bbf21696564551243c70a7
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/RoundId.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class RoundId(val value: Long)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/SearchParams.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/SearchParams.kt
new file mode 100644
index 0000000000000000000000000000000000000000..90cd95dc520e947d4e3d57cdfaf7aa6955bf6d97
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/SearchParams.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class SearchParams(val value: ByteArray) {
+
+    companion object {
+        val placeholder: ByteArray = byteArrayOf()
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/SendReport.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/SendReport.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8226a6664132985184a07368cc19854c2d6d1042
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/SendReport.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+internal value class SendReport(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/UdAddress.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/UdAddress.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c0f1b03d7ca22458cc3988bcf93a12eeceefadcf
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/UdAddress.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class UdIpAddress(val value: String)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/bindings/model/UdCertificate.kt b/app/src/main/java/io/elixxir/dapp/bindings/model/UdCertificate.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f4b9aa8f64ac56913a3d2dacfb4187709d3ba5f3
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/bindings/model/UdCertificate.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.bindings.model
+
+@JvmInline
+value class UdCertificate(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/group/model/Group.kt b/app/src/main/java/io/elixxir/dapp/group/model/Group.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6e97e6a94ce0c84a2d9c1cba75e7c31f8029a9bc
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/group/model/Group.kt
@@ -0,0 +1,11 @@
+package io.elixxir.dapp.group.model
+
+import io.elixxir.dapp.user.model.User
+
+interface Group {
+    val groupId: GroupId
+    val name: String
+    val description: String
+    val members: List<User>
+    val creator: User
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/group/model/GroupId.kt b/app/src/main/java/io/elixxir/dapp/group/model/GroupId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8cd1a184f4d5ae548a42e32238e292575ff1c39b
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/group/model/GroupId.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.group.model
+
+@JvmInline
+value class GroupId(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/logger/data/Logger.kt b/app/src/main/java/io/elixxir/dapp/logger/data/Logger.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c2dd325844c7ade7fb7a03a358266dac4fb11e69
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/logger/data/Logger.kt
@@ -0,0 +1,23 @@
+package io.elixxir.dapp.logger.data
+
+import io.elixxir.dapp.logger.model.LoggerConfig
+import io.elixxir.dapp.logger.model.LogLevel
+
+internal interface Logger {
+    val config: LoggerConfig
+
+    fun logFatal(message: String) = log(message, LogLevel.Fatal)
+    fun logError(message: String) = log(message, LogLevel.Error)
+    fun logWarn(message: String) = log(message, LogLevel.Warn)
+    fun log(message: String, level: LogLevel = LogLevel.Debug): () -> Unit = {
+        if (config.logLevel <= level) {
+            config.logWriter(message)
+        }
+    }
+
+    companion object {
+        fun newInstance(config: LoggerConfig) = object : Logger {
+            override val config: LoggerConfig = config
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/logger/data/NoLogging.kt b/app/src/main/java/io/elixxir/dapp/logger/data/NoLogging.kt
new file mode 100644
index 0000000000000000000000000000000000000000..064485546ec7380173bdb81b54609b38c4fd9561
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/logger/data/NoLogging.kt
@@ -0,0 +1,9 @@
+package io.elixxir.dapp.logger.data
+
+import io.elixxir.dapp.logger.model.LogLevel
+import io.elixxir.dapp.logger.model.LoggerConfig
+
+data class NoLogging(
+    override val logLevel: LogLevel = LogLevel.None,
+    override val logWriter: (String) -> Unit = {}
+) : LoggerConfig
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/logger/data/Timber.kt b/app/src/main/java/io/elixxir/dapp/logger/data/Timber.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cc1eb579fc360df1ed21976d42dcae289c31ce70
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/logger/data/Timber.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.logger.data
+
+import io.elixxir.dapp.logger.model.LoggerConfig
+import io.elixxir.dapp.logger.model.LogLevel
+import timber.log.Timber
+
+internal data class Timber(
+    override val logLevel: LogLevel = LogLevel.Debug,
+    override val logWriter: (String) -> Unit = { Timber.v(it) }
+) : LoggerConfig
diff --git a/app/src/main/java/io/elixxir/dapp/logger/model/LogLevel.kt b/app/src/main/java/io/elixxir/dapp/logger/model/LogLevel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1147f7423eab6e5f59813044e50d3aeea4067126
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/logger/model/LogLevel.kt
@@ -0,0 +1,20 @@
+package io.elixxir.dapp.logger.model
+
+enum class LogLevel(val code: Long) {
+    Trace(0),
+    Debug(1),
+    Info(2),
+    Warn(3),
+    Error(4),
+    Critical(5),
+    Fatal(6),
+    None(Long.MAX_VALUE);
+
+    companion object {
+        fun from(code: Long): LogLevel {
+            return values().firstOrNull {
+                it.code == code
+            } ?: throw(IllegalArgumentException("Invalid code"))
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/logger/model/LoggerConfig.kt b/app/src/main/java/io/elixxir/dapp/logger/model/LoggerConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ee5b449e77f1c6152394697ed546032cdcf0e3c9
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/logger/model/LoggerConfig.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.logger.model
+
+/**
+ * Responsible for routing helpful output of [logLevel] severity or greater
+ * to the provided [logWriter].
+ */
+interface LoggerConfig {
+    val logLevel: LogLevel
+    val logWriter: (String) -> Unit
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/messaging/model/Message.kt b/app/src/main/java/io/elixxir/dapp/messaging/model/Message.kt
new file mode 100644
index 0000000000000000000000000000000000000000..964cb63562895b09215faefe4d616ff62301c649
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/messaging/model/Message.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.messaging.model
+
+interface Message {
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/network/data/NetworkManager.kt b/app/src/main/java/io/elixxir/dapp/network/data/NetworkManager.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7bdcf4d1e28ddc440563e5bfdde6a113893959a6
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/network/data/NetworkManager.kt
@@ -0,0 +1,94 @@
+package io.elixxir.dapp.network.data
+
+import bindings.Bindings
+import bindings.Cmix
+import io.elixxir.dapp.bindings.data.AuthCallbacksAdapter
+import io.elixxir.dapp.bindings.data.CmixAdapter
+import io.elixxir.dapp.bindings.data.E2e
+import io.elixxir.dapp.bindings.data.E2eAdapter
+import io.elixxir.dapp.bindings.model.E2eParams
+import io.elixxir.dapp.bindings.model.ReceptionIdentity
+import io.elixxir.dapp.api.model.CommonProperties
+import io.elixxir.dapp.network.model.*
+import io.elixxir.dapp.network.repository.NdfDataSource
+import io.elixxir.dapp.session.model.*
+import io.elixxir.dapp.session.repository.SessionKeyStore
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.withContext
+
+internal interface NetworkManager {
+    val connectionStatus: Flow<ConnectionStatus>
+}
+
+internal class DappNetworkManager private constructor(
+    properties: CommonProperties,
+    keyStore: SessionKeyStore,
+    ndfSource: NdfDataSource
+): NetworkManager, CommonProperties by properties {
+
+    override val connectionStatus: Flow<ConnectionStatus> by ::_connectionStatus
+    private val _connectionStatus: MutableStateFlow<ConnectionStatus> =
+        MutableStateFlow(ConnectionStatus.DISCONNECTED)
+
+    fun login(
+        cmixId: Long,
+        authCallbacks: AuthCallbacksAdapter,
+        identity: ReceptionIdentity,
+        e2eParamsJson: E2eParams
+    ): E2e {
+        return E2eAdapter(
+            Bindings.login(cmixId, authCallbacks.value, identity.value, e2eParamsJson.value)
+        )
+    }
+
+    fun newCmix(
+        ndfJson: String,
+        sessionFolderPath: String,
+        sessionPassword: SessionPassword,
+        registrationCode: String
+    ) {
+        Bindings.newCmix(
+            ndfJson,
+            sessionFolderPath,
+            sessionPassword.value,
+            registrationCode
+        )
+    }
+
+    suspend fun loadCmix(
+        sessionFolderPath: String,
+        sessionPassword: SessionPassword,
+        cmixParamsJson: E2eParams
+    ): CmixAdapter = withContext(dispatcher) {
+        CmixAdapter(
+            Bindings.loadCmix(sessionFolderPath, sessionPassword.value, cmixParamsJson.value)
+        )
+    }
+
+    fun createIdentity(): ReceptionIdentity {
+        return ReceptionIdentity(
+            Cmix().makeReceptionIdentity()
+        )
+    }
+
+    fun initNetworkFollower() {
+
+    }
+
+    fun stopNetworkFollower() {
+
+    }
+
+    fun initUserDiscovery() {
+
+    }
+
+    companion object {
+        internal fun newInstance(
+            properties: CommonProperties,
+            keyStore: SessionKeyStore,
+            ndfSource: NdfDataSource
+        ) = DappNetworkManager(properties, keyStore, ndfSource)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/network/model/ConnectionStatus.kt b/app/src/main/java/io/elixxir/dapp/network/model/ConnectionStatus.kt
new file mode 100644
index 0000000000000000000000000000000000000000..39e8f6061b41f12b97efd6610d9877c3c1da9507
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/network/model/ConnectionStatus.kt
@@ -0,0 +1,5 @@
+package io.elixxir.dapp.network.model
+
+enum class ConnectionStatus {
+    DISCONNECTED, CONNECTING, CONNECTED
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/network/model/Environment.kt b/app/src/main/java/io/elixxir/dapp/network/model/Environment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..03e52f196c707327935baca045b5924b6ce19f41
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/network/model/Environment.kt
@@ -0,0 +1,5 @@
+package io.elixxir.dapp.network.model
+
+enum class Environment {
+    MainNet, ReleaseNet
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/network/model/NetworkConfig.kt b/app/src/main/java/io/elixxir/dapp/network/model/NetworkConfig.kt
new file mode 100644
index 0000000000000000000000000000000000000000..849714c06433d21bd316f5351e25e4457d0fa086
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/network/model/NetworkConfig.kt
@@ -0,0 +1,41 @@
+package io.elixxir.dapp.network.model
+
+import androidx.annotation.RawRes
+import io.elixxir.dapp.R
+import io.elixxir.dapp.api.model.CriticalRemoteDataStrategy
+import io.elixxir.dapp.api.model.RetryStrategy
+
+interface NetworkConfig {
+    val environment: Environment get() = Environment.MainNet
+    val retryStrategy: RetryStrategy get() = CriticalRemoteDataStrategy()
+}
+
+internal abstract class NdfSettings : NetworkConfig {
+    abstract val ndfUrl: String
+    abstract val certificateRef: Int
+
+    companion object {
+        fun create(config: NetworkConfig): NdfSettings {
+            return when (config.environment) {
+                Environment.MainNet -> MainNet(config.retryStrategy)
+                Environment.ReleaseNet -> ReleaseNet(config.retryStrategy)
+            }
+        }
+    }
+}
+
+internal data class MainNet(
+    override val retryStrategy: RetryStrategy,
+    override val ndfUrl: String =
+        "https://elixxir-bins.s3.us-west-1.amazonaws.com/ndf/mainnet.json",
+    @RawRes
+    override val certificateRef: Int = R.raw.mainnet,
+) : NdfSettings()
+
+internal data class ReleaseNet(
+    override val retryStrategy: RetryStrategy,
+    override val ndfUrl: String =
+        "https://elixxir-bins.s3.us-west-1.amazonaws.com/ndf/release.json",
+    @RawRes
+    override val certificateRef: Int = R.raw.release
+) : NdfSettings()
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/network/repository/NdfDataSource.kt b/app/src/main/java/io/elixxir/dapp/network/repository/NdfDataSource.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d62d49d2fa95999033ee896c036518966ac761fb
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/network/repository/NdfDataSource.kt
@@ -0,0 +1,61 @@
+package io.elixxir.dapp.network.repository
+
+import androidx.annotation.RawRes
+import io.elixxir.dapp.api.model.CommonProperties
+import io.elixxir.dapp.api.model.RetryStrategy
+import io.elixxir.dapp.bindings.data.Bindings
+import io.elixxir.dapp.network.model.NdfSettings
+import kotlinx.coroutines.*
+typealias Ndf = String
+
+internal interface NdfDataSource {
+    suspend fun fetchNdf(): Ndf
+}
+
+internal class RemoteNdfDataSource private constructor(
+    properties: CommonProperties,
+    private val settings: NdfSettings,
+    private val bindings: Bindings
+) : NdfDataSource,
+    CommonProperties by properties,
+    RetryStrategy by settings.retryStrategy
+{
+
+    override suspend fun fetchNdf(): Ndf {
+        return retryFetchNdf()
+    }
+
+    private suspend fun retryFetchNdf(retries: Int = 0): Ndf = withContext(dispatcher) {
+        val ndf = downloadAndVerifySignedNdfWithUrl(
+            settings.ndfUrl,
+            readCertificate(settings.certificateRef)
+        )
+
+        if (ndf.isEmpty() && retries <= maxRetries) {
+            ensureActive()
+            delay(retryDelayMs)
+            retryFetchNdf(retries + 1)
+        } else {
+            ndf
+        }
+    }
+
+    private fun downloadAndVerifySignedNdfWithUrl(
+        url: String,
+        certificate: String
+    ): Ndf = bindings.fetchSignedNdf(url, certificate)
+
+    private fun readCertificate(@RawRes certRef: Int): String {
+        val reader= context().resources.openRawResource(certRef)
+            .bufferedReader()
+        return reader.use { reader.readText() }
+    }
+
+    companion object {
+        internal fun newInstance(
+            properties: CommonProperties,
+            settings: NdfSettings,
+            bindings: Bindings
+        ) = RemoteNdfDataSource(properties, settings, bindings)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/preferences/KeyStorePreferences.kt b/app/src/main/java/io/elixxir/dapp/preferences/KeyStorePreferences.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6ab3d5799d7bcb80bb2d7fda00321012cbbac567
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/preferences/KeyStorePreferences.kt
@@ -0,0 +1,5 @@
+package io.elixxir.dapp.preferences
+
+interface KeyStorePreferences {
+    var password: String
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/request/model/Request.kt b/app/src/main/java/io/elixxir/dapp/request/model/Request.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2d6ca6ef3e8588793ef2cf2883f48dbcd968621f
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/request/model/Request.kt
@@ -0,0 +1,8 @@
+package io.elixxir.dapp.request.model
+
+interface Request {
+}
+
+interface OutgoingRequest : Request
+interface IncomingRequest: Request
+interface RequestConfirmation: Request
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/session/model/SecureHardwareException.kt b/app/src/main/java/io/elixxir/dapp/session/model/SecureHardwareException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2475ec6abf4643bc691cb4d040a0937d74b6aed2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/session/model/SecureHardwareException.kt
@@ -0,0 +1,6 @@
+package io.elixxir.dapp.session.model
+
+class SecureHardwareException : Exception() {
+    override val message: String
+        get() = "OS is not hardware-backed and require secure hardware is enabled."
+}
diff --git a/app/src/main/java/io/elixxir/dapp/session/model/SessionPassword.kt b/app/src/main/java/io/elixxir/dapp/session/model/SessionPassword.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8dfddc9fee4259416d3ffe3e1fde7cdabbdc655b
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/session/model/SessionPassword.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.session.model
+
+@JvmInline
+value class SessionPassword(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/session/repository/SessionDataSource.kt b/app/src/main/java/io/elixxir/dapp/session/repository/SessionDataSource.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3f316d7f3800ed962dc298ed1081d614dd7d521e
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/session/repository/SessionDataSource.kt
@@ -0,0 +1,88 @@
+package io.elixxir.dapp.session.repository
+
+import java.io.File
+import io.elixxir.dapp.api.model.CommonProperties
+import kotlinx.coroutines.*
+
+/**
+ * Responsible for creation, deletion & storage of folder used to persist
+ * Cmix session.
+ */
+internal interface SessionDataSource {
+    val sessionFolder: File
+
+    fun doesSessionExist(): Boolean
+
+    /**
+     * Only needs to be created once per app installation.
+     * Return the [sessionFolder] if successful.
+     */
+    suspend fun createSession(): Result<File>
+
+    /**
+     * Should be called during account deletion.
+     */
+    suspend fun deleteSession(): Result<Unit>
+
+    /**
+     * Restore session
+     */
+    suspend fun restoreSession(): Result<Unit>
+}
+
+internal class LocalSessionDataSource private constructor(
+    properties: CommonProperties
+) : SessionDataSource, CommonProperties by properties {
+
+    override val sessionFolder: File get() {
+        return try {
+            File(context().filesDir, "cmix/session")
+        } catch (e: Exception) {
+            logFatal(e.message ?: "Couldn't access filesDir.")
+            throw e
+        }
+    }
+
+    override fun doesSessionExist(): Boolean = sessionFolder.exists()
+
+    override suspend fun createSession(): Result<File> = withContext(dispatcher) {
+        try {
+            Result.success(createSessionFolder())
+        } catch (e: Exception) {
+            Result.failure(e)
+        }
+    }
+
+    private fun createSessionFolder(): File {
+        return sessionFolder.apply {
+            if (exists()) {
+                log("Session folder from previous installation was found.")
+                log("It contains ${listFiles()?.size ?: 0} files.")
+                log("Deleting!")
+                deleteRecursively()
+            }
+            mkdir()
+            log("Session folder successfully created at: $absolutePath")
+        }
+    }
+
+    override suspend fun deleteSession(): Result<Unit> = withContext(dispatcher) {
+        try {
+            if (sessionFolder.deleteRecursively()) {
+                Result.success(Unit)
+            } else {
+                Result.failure(Exception("Failed to delete all files."))
+            }
+        } catch (e: Exception) {
+            Result.failure(e)
+        }
+    }
+
+    override suspend fun restoreSession(): Result<Unit> {
+        TODO("Not yet implemented")
+    }
+
+    companion object {
+        internal fun newInstance(properties: CommonProperties) = LocalSessionDataSource(properties)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/session/repository/SessionKeyStore.kt b/app/src/main/java/io/elixxir/dapp/session/repository/SessionKeyStore.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0607c31fb2eb2b86c84347e4cc86a2b4bfc5dc64
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/session/repository/SessionKeyStore.kt
@@ -0,0 +1,238 @@
+package io.elixxir.dapp.session.repository
+
+import android.os.Build
+import android.security.keystore.KeyGenParameterSpec
+import android.security.keystore.KeyInfo
+import android.security.keystore.KeyProperties
+import io.elixxir.dapp.api.model.CommonProperties
+import io.elixxir.dapp.bindings.data.Bindings
+import io.elixxir.dapp.preferences.KeyStorePreferences
+import io.elixxir.dapp.session.model.SecureHardwareException
+import io.elixxir.dapp.session.model.SessionPassword
+import io.elixxir.dapp.util.fromBase64toByteArray
+import io.elixxir.dapp.util.toBase64String
+import kotlinx.coroutines.withContext
+import java.security.*
+import java.security.spec.MGF1ParameterSpec
+import java.security.spec.RSAKeyGenParameterSpec
+import javax.crypto.BadPaddingException
+import javax.crypto.Cipher
+import javax.crypto.IllegalBlockSizeException
+import javax.crypto.NoSuchPaddingException
+import javax.crypto.spec.OAEPParameterSpec
+import javax.crypto.spec.PSource
+import kotlin.system.measureTimeMillis
+
+internal interface SessionKeyStore {
+    suspend fun createSessionPassword(requireSecureHardware: Boolean): Result<Unit>
+    suspend fun rsaDecryptPassword(): SessionPassword
+}
+
+internal class DappSessionKeystore private constructor(
+    properties: CommonProperties,
+    private val preferences: KeyStorePreferences,
+    private val bindings: Bindings
+) : SessionKeyStore, CommonProperties by properties {
+
+    override suspend fun createSessionPassword(requireSecureHardware: Boolean): Result<Unit> =
+        withContext(dispatcher) {
+            if (requireSecureHardware && !isHardwareBackedKeyStore()) {
+                return@withContext Result.failure(SecureHardwareException())
+            }
+
+            try {
+                deletePreviousKeys()
+                generateKeys()
+                generatePassword()
+                Result.success(Unit)
+            } catch (e: Exception) {
+                logError(e.message ?: "An error occured while creating session password.")
+                Result.failure(e)
+            }
+    }
+
+    private fun generatePassword() {
+        val encryptionTime = measureTimeMillis {
+            val passwordLength = PASSWORD_LENGTH
+            log("Generating a password...")
+            log("Generating a password with $passwordLength bytes")
+
+            var secret: SessionPassword
+            val generationTime = measureTimeMillis {
+                do {
+                    secret = bindings.generateSecret(passwordLength)
+                    log("Password (Bytearray): $secret")
+                    log("Password (String64): ${secret.value.toBase64String()}")
+
+                    val isAllZeroes = byteArrayOf(passwordLength.toByte()).contentEquals(secret.value)
+                    log("IsAllZeroes: $isAllZeroes")
+                } while (isAllZeroes)
+            }
+            log("Total generation time: $generationTime ms")
+            rsaEncryptPwd(secret.value)
+        }
+        log("Total encryption time: $encryptionTime ms")
+    }
+
+    private fun deletePreviousKeys() {
+        val keystore = getKeystore()
+        if (keystore.containsAlias(KEY_ALIAS)) {
+            log("Deleting key alias")
+            keystore.deleteEntry(KEY_ALIAS)
+        }
+    }
+
+    private fun checkGenerateKeys(): Boolean {
+        return try {
+            val areKeysGenerated = generateKeys()
+            if (areKeysGenerated) {
+                log("Keystore keys successfully generated")
+                true
+            } else {
+                log("Error generating keystore keys")
+                false
+            }
+        } catch (err: Exception) {
+            log("An error occured while generating keys.")
+            false
+        }
+    }
+
+    private fun generateKeys(): Boolean {
+        val keystore = getKeystore()
+        if (!keystore.containsAlias(KEY_ALIAS)) {
+            log("Keystore alias does not exist, credentials")
+            val keyGenerator = getKeyPairGenerator()
+            keyGenerator.genKeyPair()
+        } else {
+            log("Keystore alias already exist")
+        }
+
+        return true
+    }
+
+    private fun getKeyPairGenerator(): KeyPairGenerator {
+        val keyGenerator = KeyPairGenerator.getInstance(
+            KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore"
+        )
+        val keyGenParameterSpec = getKeygenParamSpec()
+        keyGenerator.initialize(keyGenParameterSpec)
+        return keyGenerator
+    }
+
+    private fun getPrivateKey(): PrivateKey? {
+        val keyStore: KeyStore = getKeystore()
+        return keyStore.getKey(KEY_ALIAS, null) as PrivateKey?
+    }
+
+    private fun getPublicKey(): PublicKey {
+        return getKeystore().getCertificate(KEY_ALIAS).publicKey
+    }
+
+    private fun getKeystore(): KeyStore {
+        val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
+        keyStore.load(null)
+        return keyStore
+    }
+
+    private fun getKeygenParamSpec(): KeyGenParameterSpec {
+        val keyGenSpec = KeyGenParameterSpec.Builder(
+            KEY_ALIAS,
+            KEY_PURPOSE
+        ).setAlgorithmParameterSpec(RSAKeyGenParameterSpec(KEY_SIZE, RSAKeyGenParameterSpec.F4))
+            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
+            .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
+            .setDigests(KeyProperties.DIGEST_SHA1)
+            .setRandomizedEncryptionRequired(true)
+
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+            keyGenSpec.setUserAuthenticationParameters(
+                1000,
+                KeyProperties.AUTH_BIOMETRIC_STRONG or KeyProperties.AUTH_DEVICE_CREDENTIAL
+            )
+        } else {
+            keyGenSpec.setUserAuthenticationValidityDurationSeconds(1000)
+        }
+
+        return keyGenSpec.build()
+    }
+
+    @Throws(
+        NoSuchAlgorithmException::class,
+        NoSuchPaddingException::class,
+        InvalidKeyException::class,
+        IllegalBlockSizeException::class,
+        BadPaddingException::class
+    )
+    private fun rsaEncryptPwd(pwd: ByteArray): ByteArray {
+        log("Bytecount: ${pwd.size}")
+        log("Before encryption: ${pwd.toBase64String()}")
+        val secretKey = getPublicKey()
+
+        val cipher = Cipher.getInstance(KEYSTORE_ALGORITHM)
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey, cipherMode)
+        val encryptedBytes = cipher.doFinal(pwd)
+        log("Encrypted: ${encryptedBytes.toBase64String()}")
+        preferences.password = encryptedBytes.toBase64String()
+
+        return encryptedBytes
+    }
+
+    @Throws(
+        NoSuchAlgorithmException::class,
+        NoSuchPaddingException::class,
+        InvalidKeyException::class,
+        IllegalBlockSizeException::class,
+        BadPaddingException::class
+    )
+    override suspend fun rsaDecryptPassword(): SessionPassword = withContext(dispatcher) {
+        val encryptedBytes = preferences.password.fromBase64toByteArray()
+        val key = getPrivateKey()
+        val cipher1 = Cipher.getInstance(KEYSTORE_ALGORITHM)
+        println("Initializing Decrypt")
+        cipher1.init(Cipher.DECRYPT_MODE, key, cipherMode)
+        val decryptedBytes = cipher1.doFinal(encryptedBytes)
+        println("Decrypted: ${decryptedBytes.toBase64String()}")
+
+        SessionPassword(decryptedBytes)
+    }
+
+    private fun isHardwareBackedKeyStore(): Boolean {
+        return try {
+            val privateKey = getPrivateKey()
+            val keyFactory = KeyFactory.getInstance(privateKey?.algorithm, ANDROID_KEYSTORE)
+            val keyInfo: KeyInfo = keyFactory.getKeySpec(privateKey, KeyInfo::class.java)
+            val securityLevel = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+                (keyInfo.securityLevel == KeyProperties.SECURITY_LEVEL_TRUSTED_ENVIRONMENT ||
+                        keyInfo.securityLevel == KeyProperties.SECURITY_LEVEL_STRONGBOX)
+            } else {
+                keyInfo.isInsideSecureHardware
+            }
+            return securityLevel
+        } catch (e: Exception) {
+            logError(e.message ?: "An error occured while checking hardware backed key store.")
+            false
+        }
+    }
+
+    companion object {
+        private const val KEY_ALIAS = "dAppSession"
+        private const val ANDROID_KEYSTORE = "AndroidKeyStore"
+        private const val KEY_PURPOSE =
+            KeyProperties.PURPOSE_SIGN or KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT
+        private const val KEYSTORE_ALGORITHM = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"
+        private const val KEY_SIZE = 2048
+        private val cipherMode = OAEPParameterSpec(
+            "SHA-1", "MGF1",
+            MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT
+        )
+        private const val PASSWORD_LENGTH = 64L
+
+        internal fun newInstance(
+            properties: CommonProperties,
+            preferences: KeyStorePreferences,
+            bindings: Bindings
+        ) = DappSessionKeystore(properties, preferences, bindings)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/user/model/User.kt b/app/src/main/java/io/elixxir/dapp/user/model/User.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c24e22376e3aca42596669f4387cc917c91789d2
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/user/model/User.kt
@@ -0,0 +1,18 @@
+package io.elixxir.dapp.user.model
+
+interface User {
+    val userId: Long
+    val username: String
+    val phone: String?
+    val email: String?
+
+    companion object {
+        val placeholder = object : User {
+            override val userId: Long = 0
+            override val username: String = ""
+            override val phone: String? = null
+            override val email: String? = null
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/user/model/UserId.kt b/app/src/main/java/io/elixxir/dapp/user/model/UserId.kt
new file mode 100644
index 0000000000000000000000000000000000000000..92d92772ac1ef0ea51548c1cd2d53feec78c5436
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/user/model/UserId.kt
@@ -0,0 +1,4 @@
+package io.elixxir.dapp.user.model
+
+@JvmInline
+value class UserId(val value: ByteArray)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/user/model/UserQuery.kt b/app/src/main/java/io/elixxir/dapp/user/model/UserQuery.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0debdfb23fcd0d389c3c21fc4b2322e5018551b9
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/user/model/UserQuery.kt
@@ -0,0 +1,10 @@
+package io.elixxir.dapp.user.model
+
+interface UserQuery {
+    val query: String
+    val queryType: QueryType
+
+    enum class QueryType {
+        USERNAME, USERID, PHONE, EMAIL
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/user/model/UserUpdateData.kt b/app/src/main/java/io/elixxir/dapp/user/model/UserUpdateData.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0df45d32dc36cf7d20e9667e28d19b09916ac154
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/user/model/UserUpdateData.kt
@@ -0,0 +1,6 @@
+package io.elixxir.dapp.user.model
+
+data class UserUpdateData(
+    val newPhone: String?,
+    val newEmail: String?
+)
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/user/repository/UserDataSource.kt b/app/src/main/java/io/elixxir/dapp/user/repository/UserDataSource.kt
new file mode 100644
index 0000000000000000000000000000000000000000..037e4f40c06759d7da7c7c66f8448449c3a5f751
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/user/repository/UserDataSource.kt
@@ -0,0 +1,36 @@
+package io.elixxir.dapp.user.repository
+
+import io.elixxir.dapp.bindings.data.UserDiscovery
+import io.elixxir.dapp.api.model.CommonProperties
+import io.elixxir.dapp.user.model.User
+
+interface UserDataSource {
+    suspend fun createUser(username: String): Result<User>
+    suspend fun updateProfile(): Result<User>
+    suspend fun deleteProfile(): Result<Unit>
+}
+
+internal class RemoteUserDataSource private constructor(
+    properties: CommonProperties,
+    private val ud: UserDiscovery
+) : UserDataSource, CommonProperties by properties {
+
+    override suspend fun createUser(username: String): Result<User> {
+        TODO("Not yet implemented")
+    }
+
+    override suspend fun updateProfile(): Result<User> {
+        TODO("Not yet implemented")
+    }
+
+    override suspend fun deleteProfile(): Result<Unit> {
+        TODO("Not yet implemented")
+    }
+
+    companion object {
+        internal fun newInstance(
+            properties: CommonProperties,
+            ud: UserDiscovery
+        ) = RemoteUserDataSource(properties, ud)
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/elixxir/dapp/util/ByteArray.kt b/app/src/main/java/io/elixxir/dapp/util/ByteArray.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a7cd66b8448698fd37a215414766aebd25a9f02e
--- /dev/null
+++ b/app/src/main/java/io/elixxir/dapp/util/ByteArray.kt
@@ -0,0 +1,11 @@
+package io.elixxir.dapp.util
+
+import android.util.Base64
+
+fun ByteArray.toBase64String(): String {
+    return Base64.encodeToString(this, Base64.NO_WRAP)
+}
+
+fun String.fromBase64toByteArray(): ByteArray {
+    return Base64.decode(this, Base64.NO_WRAP)
+}
\ No newline at end of file
diff --git a/app/src/main/res/raw/mainnet.crt b/app/src/main/res/raw/mainnet.crt
new file mode 100644
index 0000000000000000000000000000000000000000..096e3b5cda98b012d892d6531ab1a4696d13a457
--- /dev/null
+++ b/app/src/main/res/raw/mainnet.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFqTCCA5GgAwIBAgIUO0qHXSeKrOMucO+Zz82Mf1Zlq4gwDQYJKoZIhvcNAQEL
+BQAwgYAxCzAJBgNVBAYTAktZMRQwEgYDVQQHDAtHZW9yZ2UgVG93bjETMBEGA1UE
+CgwKeHggbmV0d29yazEPMA0GA1UECwwGRGV2T3BzMRMwEQYDVQQDDAp4eC5uZXR3
+b3JrMSAwHgYJKoZIhvcNAQkBFhFhZG1pbnNAeHgubmV0d29yazAeFw0yMTEwMzAy
+MjI5MjZaFw0zMTEwMjgyMjI5MjZaMIGAMQswCQYDVQQGEwJLWTEUMBIGA1UEBwwL
+R2VvcmdlIFRvd24xEzARBgNVBAoMCnh4IG5ldHdvcmsxDzANBgNVBAsMBkRldk9w
+czETMBEGA1UEAwwKeHgubmV0d29yazEgMB4GCSqGSIb3DQEJARYRYWRtaW5zQHh4
+Lm5ldHdvcmswggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQD08ixnPWwz
+FtBIEWx2SnFjBsdrSWCp9NcWXRtGWeq3ACz+ixiflj/U9U4b57aULeOAvcoC7bwU
+j5w3oYxRmXIV40QSevx1z9mNcW3xbbacQ+yCgPPhhj3/c285gVVOUzURLBTNAi9I
+EA59zAb8Vy0E6zfq4HRAhH11Q/10QgDjEXuGXra1k3IlemVsouiJGNAtKojNDE1N
+x9HnraSEiXzdnV2GDplEvMHaLd3s9vs4XsiLB3VwKyHv7EH9+LOIra6pr5BWw+kD
+2qHKGmQMOQe0a7nCirW/k9axH0WiA0XWuQu3U1WfcMEfdC/xn1vtubrdYjtzpXUy
+oUEX5eHfu4OlA/zoH+trocfARDyBmTVbDy0P9imH//a6GUKDui9r3fXwEy5YPMhb
+dKaNc7QWLPHMh1n25h559z6PqxxPT6UqFFbZD2gTw1sbbpjyqhLbnYguurkxY3jZ
+ztW337hROzQ1/abbg/P59JA95Pmhkl8nqqDEf0buOmvMazq3Lwg92nuZ8gsdMKXB
+xaEtTTpxhTPOqzc1/XQgScZnc+092MBDh3C2GMxzylOIdk+yF2Gyb+VWPUe29dSa
+azzxsDXzRy8y8jaOjdSUWaLa/MgS5Dg1AfHtD55bdvqYzw3NEXIVarpMlzl+Z+6w
+jvuwz8GyoMSVe+YEGgvSDvlfY/z19aqneQIDAQABoxkwFzAVBgNVHREEDjAMggp4
+eC5uZXR3b3JrMA0GCSqGSIb3DQEBCwUAA4ICAQCp0JDub2w5vZQvFREyA+utZ/+s
+XT05j1iTgIRKMa3nofDGERYJUG7FcTd373I2baS70PGx8FF1QuXhn4DNNZlW/SZt
+pa1d0pAerqFrIzwOuWVDponYHQ8ayvsT7awCbwZEZE4RhooqS4LqnvtgFu/g7LuM
+zkFN8TER7HAUn3P7BujLvcgtqk2LMDz+AgBRszDp/Bw7+1EJDeG9d7hC/stXgDV/
+vpD1YDpxSmW4zjezFJqV6OdMOwo9RWVIktK3RXbFc6I5UJZ5kmzPe/I2oPPCBQvD
+G3VqFLQe5ik5rXP7SgAN1fL/7KuQna0s42hkV64Z2ymCX69G1ofpgpEFaQLaxLbj
+QOun0r8A3NyKvHRIh4K0dFcc3FSOF60Y6k769HKbOPmSDjSSg0qO9GEONBJ8BxAT
+IHcHoTAOQoqGehdzepXQSjHsPqTXv3ZFFwCCgO0toI0Qhqwo89X6R3k+i4Kaktr7
+mLiPO8s0nq1PZ1XrybKE9BCHkYH1JkUDA+M0pn4QAEx/BuM0QnGXoi1sImW3pEUG
+NP7fjkISrD48P8P/TLS45sx5pB8MNGEsRw0lBKmuOdWDmdfhOltB6JxmbhpstNZp
+6LVLK6SEOwE76xnHiisR2KyhTTiroUq73BgPFWkWhoJDPbmL1DHgnbdKwwstG8Qu
+UGb8k8vh6tzqYZAOKg==
+-----END CERTIFICATE-----
diff --git a/app/src/main/res/raw/release.crt b/app/src/main/res/raw/release.crt
new file mode 100644
index 0000000000000000000000000000000000000000..b8d5847f8709d8f888f32ce2024dcffe33af4131
--- /dev/null
+++ b/app/src/main/res/raw/release.crt
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFtjCCA56gAwIBAgIJAJnUcpLbGSQiMA0GCSqGSIb3DQEBCwUAMIGMMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExEjAQBgNVBAcMCUNsYXJlbW9udDEQMA4GA1UE
+CgwHRWxpeHhpcjEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxEzARBgNVBAMMCmVsaXh4
+aXIuaW8xHzAdBgkqhkiG9w0BCQEWEGFkbWluQGVsaXh4aXIuaW8wHhcNMjAxMTE3
+MTkwMTUyWhcNMjIxMTE3MTkwMTUyWjCBjDELMAkGA1UEBhMCVVMxCzAJBgNVBAgM
+AkNBMRIwEAYDVQQHDAlDbGFyZW1vbnQxEDAOBgNVBAoMB0VsaXh4aXIxFDASBgNV
+BAsMC0RldmVsb3BtZW50MRMwEQYDVQQDDAplbGl4eGlyLmlvMR8wHQYJKoZIhvcN
+AQkBFhBhZG1pbkBlbGl4eGlyLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAvtByOoSS8SeMLvvHIuOGfnx0VgweveJHX93LUyJxr1RlVBXCgC5/QOQN
+N3dmKWzu4YwaA2jtwaAMhkgdfyOcw6kuqfvQjxv99XRIRKM4GZQkJiym2cnorNu7
+hm2/bxmj5TjpP9+vFzbjkJrpRQ80hsV7I9+NKzIhMK4YTgte/F/q9URESlMZxTbb
+MFh3s5iiBfBLRNFFsHVdy8OVH+Jv5901cLn+yowaMDLrBMOWGlRROg82ZeRAranX
+9X1s+6BclJ/cBe/LcDxGso5sco6UzrWHzpDTnOTzHoamQHYCXtAZP4XbzcqI6A5i
+GFM2akuG9Wv3XZZv/6eJRnKS2GLkvv7dtzv+nalxoBKtyIE8ICIVOrb+pVJvY1Id
+HOXkK9MEJJ6sZhddipUaQw6hD4I0dNEt30Ugq9zTgFcEnM2R7qKpIDmxrRbcl280
+TQGNYgdidzleNdZbjcTvsMVhcxPXCY+bVX1xICD1oJiZZbZFejBvPEfLYyzSdYp+
+awX5OnLVSrQtTJu9yz5q3q5pHhxJnqS/CVGLTvzLfmk7BGwRZZuK87LnSixyYfpd
+S23qI45AEUINEE0HDZsI+KBq0oVlDB0Z3AZpWauRDqY3o6JIbIOpqmZc6KntyL7j
+YCAhbB1tchS47PpbIxUgMMGoR3MBkJutPqtTWCEE3l5jvv0CknUCAwEAAaMZMBcw
+FQYDVR0RBA4wDIIKZWxpeHhpci5pbzANBgkqhkiG9w0BAQsFAAOCAgEACLoxE3nh
+3VzXH2lQo1QzjKkG/+1m75T0l9Wn9uxa2W/90qBCfim1CPfWUstGdRLBi8gjDevV
+zK5HN+Cpz2E22qByeN9fl6rJC4zd1vIdexEre5h7goWoV+qFPhOACElor1tF5UQ2
+GD+NFH+Z0ALG1u8db0hBv8NCbtD4YzcQzzINEbs9gp/Sq3cRzkz1wCufFwJwr7+R
+0YqZfPj/v/w9G9wSUys1s3i4xr2u87T/bPF68VRg6r1+kXRSRevXd99wKwap52jY
+zOwsDGZF9BHMpFVYR/yZhfzSK3F1DmvwuqOsfwSFIjrUjfRlwS28zyZ8rjBq1suD
+EAdvYCLDmBSGssNh8E20PHmk5UROYFGEEhlK5ZKj/f1HOmMiOX461XK6HODYyitq
+Six2dPi1ZlBJW83DyFqSWJaUR/CluBYmqrWoBX+chv54bU2Y9j/sA/O98wa7trsk
+ctzvAcXjhXm6ESRVVD/iZvkW5MP2mkgbDpW3RP9souK5JzbcpC7i3hEcAqPSPgzL
+94kHDpYNY7jcGQC4CjPdfBi+Tf6il/QLFRFgyHm2ze3+qrlPT6SQ4hSSH1iXyf4v
+tlqu6u77fbF9yaHtq7dvYxH1WioIUxMqbIC1CNgGC1Y/LhzgLRKPSTBCrbQyTcGc
+0b5cTzVKxdP6v6WOAXVOEkXTcBPZ4nEZxY0=
+-----END CERTIFICATE-----