diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f2666b5..bedd3f7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,7 +6,6 @@ plugins { id("com.android.application") version "9.2.0" id("org.jetbrains.kotlin.plugin.compose") version "2.3.21" id("org.jetbrains.kotlin.plugin.serialization") version "2.3.21" - id("com.google.protobuf") version "0.10.0" id("org.jlleitschuh.gradle.ktlint") version "14.2.0" } @@ -55,11 +54,12 @@ tasks.withType { dependencies { // Basic android dependencies implementation("androidx.core:core-ktx:1.17.0") - implementation("androidx.datastore:datastore:1.2.0") - implementation("com.google.protobuf:protobuf-javalite:4.33.5") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0") implementation("androidx.core:core-splashscreen:1.2.0") + // DataStore + implementation("androidx.datastore:datastore:1.2.1") + // Jetpack Compose // Adding the Bill of Materials synchronizes dependencies in the androidx.compose namespace // You can remove the library version in your dependency declarations @@ -77,7 +77,7 @@ dependencies { implementation("com.composables:icons-lucide:1.1.0") // Bitcoin Development Kit - implementation("org.bitcoindevkit:bdk-android:3.0.0-RC2") + implementation("org.bitcoindevkit:bdk-android:3.0.0") // QR codes implementation("com.google.zxing:core:3.5.4") @@ -88,22 +88,6 @@ dependencies { androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0") } -protobuf { - protoc { - artifact = "com.google.protobuf:protoc:3.25.0" - } - - generateProtoTasks { - all().forEach { task -> - task.builtins { - create("java") { - option("lite") - } - } - } - } -} - ktlint { version = "1.8.0" ignoreFailures = false diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/UserPreferencesSerializer.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/UserPreferencesSerializer.kt deleted file mode 100644 index be168a9..0000000 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/UserPreferencesSerializer.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.data - -import androidx.datastore.core.CorruptionException -import androidx.datastore.core.Serializer -import com.google.protobuf.InvalidProtocolBufferException -import java.io.InputStream -import java.io.OutputStream - -object UserPreferencesSerializer : Serializer { - override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance() - - override suspend fun readFrom(input: InputStream): UserPreferences { - try { - return UserPreferences.parseFrom(input) - } catch (exception: InvalidProtocolBufferException) { - throw CorruptionException("Cannot read proto.", exception) - } - } - - override suspend fun writeTo(t: UserPreferences, output: OutputStream) { - t.writeTo(output) - } -} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt index 495a085..8158e41 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/WalletConfigs.kt @@ -7,6 +7,7 @@ package org.bitcoindevkit.devkitwallet.data import org.bitcoindevkit.Descriptor import org.bitcoindevkit.Network +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType data class NewWalletConfig( val name: String, diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt new file mode 100644 index 0000000..9f62427 --- /dev/null +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/AppSettings.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2021-2026 thunderbiscuit and contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. + */ + +package org.bitcoindevkit.devkitwallet.data.datastore + +import androidx.datastore.core.CorruptionException +import androidx.datastore.core.Serializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.Json +import java.io.InputStream +import java.io.OutputStream + +@Serializable +data class AppSettings( + val darkTheme: Boolean = true, + val introDone: Boolean = false, +) + +object AppSettingsSerializer : Serializer { + override val defaultValue = AppSettings() + + override suspend fun readFrom(input: InputStream): AppSettings { + try { + return Json.decodeFromString(input.readBytes().decodeToString()) + } catch (e: SerializationException) { + throw CorruptionException("Cannot read AppSettings.", e) + } + } + + override suspend fun writeTo(t: AppSettings, output: OutputStream) { + output.write(Json.encodeToString(t).encodeToByteArray()) + } +} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt new file mode 100644 index 0000000..760c811 --- /dev/null +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/data/datastore/WalletData.kt @@ -0,0 +1,57 @@ +package org.bitcoindevkit.devkitwallet.data.datastore + +import androidx.datastore.core.CorruptionException +import androidx.datastore.core.Serializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.Json +import java.io.InputStream +import java.io.OutputStream + +@Serializable +enum class ActiveWalletNetwork { + TESTNET, + SIGNET, + REGTEST, +} + +@Serializable +enum class ActiveWalletScriptType { + P2WPKH, + P2TR, + UNKNOWN, +} + +@Serializable +data class StoredWallet( + val id: String, + val name: String, + val network: ActiveWalletNetwork, + val scriptType: ActiveWalletScriptType, + val descriptor: String, + val changeDescriptor: String, + val recoveryPhrase: String = "", + val fullScanCompleted: Boolean = false, +) + +@Serializable +data class WalletData( + val wallets: List = emptyList(), + // network config fields go here alongside wallets +) + +object WalletDataSerializer : Serializer { + override val defaultValue = WalletData() + + override suspend fun readFrom(input: InputStream): WalletData { + try { + return Json.decodeFromString(input.readBytes().decodeToString()) + } catch (e: SerializationException) { + throw CorruptionException("Cannot read AppSettings.", e) + } + } + + override suspend fun writeTo(t: WalletData, output: OutputStream) { + output.write(Json.encodeToString(t).encodeToByteArray()) + } +} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt new file mode 100644 index 0000000..071708c --- /dev/null +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/AppSettingsRepository.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2021-2026 thunderbiscuit and contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. + */ + +package org.bitcoindevkit.devkitwallet.domain + +import androidx.datastore.core.DataStore +import kotlinx.coroutines.flow.first +import org.bitcoindevkit.devkitwallet.data.datastore.AppSettings + +class AppSettingsRepository(private val store: DataStore) { + suspend fun fetchDarkTheme() = store.data.first().darkTheme + + suspend fun setDarkTheme(isDark: Boolean) = store.updateData { it.copy(darkTheme = isDark) } + + suspend fun fetchIntroDone() = store.data.first().introDone + + suspend fun setIntroDone() = store.updateData { it.copy(introDone = true) } +} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/UserPreferencesRepository.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/UserPreferencesRepository.kt deleted file mode 100644 index 6d36779..0000000 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/UserPreferencesRepository.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2021-2026 thunderbiscuit and contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. - */ - -package org.bitcoindevkit.devkitwallet.domain - -import androidx.datastore.core.DataStore -import kotlinx.coroutines.flow.first -import org.bitcoindevkit.devkitwallet.data.SingleWallet -import org.bitcoindevkit.devkitwallet.data.UserPreferences - -class UserPreferencesRepository( - private val userPreferencesStore: DataStore, -) { - suspend fun fetchIntroDone(): Boolean { - return userPreferencesStore.data.first().introDone - } - - suspend fun setIntroDone() { - userPreferencesStore.updateData { currentPreferences -> - currentPreferences.toBuilder().setIntroDone(true).build() - } - } - - suspend fun fetchActiveWallets(): List { - return userPreferencesStore.data.first().walletsList - } - - suspend fun updateActiveWallets(singleWallet: SingleWallet) { - userPreferencesStore.updateData { currentPreferences -> - currentPreferences.toBuilder().addWallets(singleWallet).build() - } - } - - suspend fun fetchDarkTheme(): Boolean { - return userPreferencesStore.data.first().darkTheme - } - - suspend fun setDarkTheme(isDark: Boolean) { - userPreferencesStore.updateData { currentPreferences -> - currentPreferences.toBuilder().setDarkTheme(isDark).build() - } - } - - suspend fun setFullScanCompleted(walletId: String) { - userPreferencesStore.updateData { currentPreferences -> - val updatedWalletsList = - currentPreferences.walletsList.map { wallet -> - if (wallet.id == walletId) { - wallet.toBuilder().setFullScanCompleted(true).build() - } else { - wallet - } - } - currentPreferences - .toBuilder() - .clearWallets() - .addAllWallets(updatedWalletsList) - .build() - } - } -} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt index cc41e3c..29fd725 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/Wallet.kt @@ -25,13 +25,13 @@ import org.bitcoindevkit.Script import org.bitcoindevkit.TxBuilder import org.bitcoindevkit.Update import org.bitcoindevkit.WordCount -import org.bitcoindevkit.devkitwallet.data.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.data.ConfirmationBlock import org.bitcoindevkit.devkitwallet.data.NewWalletConfig import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig -import org.bitcoindevkit.devkitwallet.data.SingleWallet import org.bitcoindevkit.devkitwallet.data.Timestamp import org.bitcoindevkit.devkitwallet.data.TxDetails +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType +import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet import org.bitcoindevkit.devkitwallet.domain.utils.intoDomain import org.bitcoindevkit.devkitwallet.domain.utils.intoProto import org.bitcoindevkit.devkitwallet.presentation.viewmodels.mvi.Recipient @@ -46,7 +46,7 @@ class Wallet private constructor( private val connection: Persister, private var fullScanCompleted: Boolean, private val walletId: String, - private val userPreferencesRepository: UserPreferencesRepository, + private val walletRepository: WalletRepository, val internalAppFilesPath: String, val network: Network, ) { @@ -190,7 +190,7 @@ class Wallet private constructor( fun createWallet( newWalletConfig: NewWalletConfig, internalAppFilesPath: String, - userPreferencesRepository: UserPreferencesRepository, + walletRepository: WalletRepository, ): Wallet { val mnemonic = Mnemonic(WordCount.WORDS12) val bip32ExtendedRootKey = DescriptorSecretKey(NetworkKind.TEST, mnemonic, null) @@ -210,21 +210,19 @@ class Wallet private constructor( val connection = Persister.newSqlite("$internalAppFilesPath/wallet-${walletId.take(8)}.sqlite3") // Create SingleWallet object for saving to datastore - val newWalletForDatastore: SingleWallet = - SingleWallet - .newBuilder() - .setId(walletId) - .setName(newWalletConfig.name) - .setNetwork(newWalletConfig.network.intoProto()) - .setScriptType(ActiveWalletScriptType.P2WPKH) - .setDescriptor(descriptor.toStringWithSecret()) - .setChangeDescriptor(changeDescriptor.toStringWithSecret()) - .setRecoveryPhrase(mnemonic.toString()) - .build() - + val newWalletForDatastore: StoredWallet = + StoredWallet( + id = walletId, + name = newWalletConfig.name, + network = newWalletConfig.network.intoProto(), + scriptType = ActiveWalletScriptType.P2WPKH, + descriptor = descriptor.toStringWithSecret(), + changeDescriptor = changeDescriptor.toStringWithSecret(), + recoveryPhrase = mnemonic.toString() + ) // TODO: launch this correctly, not on the main thread // Save the new wallet to the datastore - runBlocking { userPreferencesRepository.updateActiveWallets(newWalletForDatastore) } + runBlocking { walletRepository.addWallet(newWalletForDatastore) } val bdkWallet = BdkWallet( @@ -242,16 +240,16 @@ class Wallet private constructor( connection = connection, fullScanCompleted = false, walletId = walletId, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, internalAppFilesPath = internalAppFilesPath, network = newWalletConfig.network ) } fun loadActiveWallet( - activeWallet: SingleWallet, + activeWallet: StoredWallet, internalAppFilesPath: String, - userPreferencesRepository: UserPreferencesRepository, + walletRepository: WalletRepository, ): Wallet { val descriptor = Descriptor(activeWallet.descriptor, NetworkKind.TEST) val changeDescriptor = Descriptor(activeWallet.changeDescriptor, NetworkKind.TEST) @@ -270,7 +268,7 @@ class Wallet private constructor( connection = connection, fullScanCompleted = activeWallet.fullScanCompleted, walletId = activeWallet.id, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, internalAppFilesPath = internalAppFilesPath, network = activeWallet.network.intoDomain() ) @@ -279,7 +277,7 @@ class Wallet private constructor( fun recoverWallet( recoverWalletConfig: RecoverWalletConfig, internalAppFilesPath: String, - userPreferencesRepository: UserPreferencesRepository, + walletRepository: WalletRepository, ): Wallet { Log.i(TAG, "Recovering wallet with config: $recoverWalletConfig") var descriptor: Descriptor? = null @@ -311,21 +309,20 @@ class Wallet private constructor( val connection = Persister.newSqlite("$internalAppFilesPath/wallet-${walletId.take(8)}.sqlite3") // Create SingleWallet object for saving to datastore - val newWalletForDatastore: SingleWallet = - SingleWallet - .newBuilder() - .setId(walletId) - .setName(recoverWalletConfig.name) - .setNetwork(recoverWalletConfig.network.intoProto()) - .setScriptType(recoverWalletConfig.scriptType ?: ActiveWalletScriptType.UNKNOWN) - .setDescriptor(descriptor.toStringWithSecret()) - .setChangeDescriptor(changeDescriptor.toStringWithSecret()) - .setRecoveryPhrase(mnemonicString) - .build() + val newWalletForDatastore: StoredWallet = + StoredWallet( + id = walletId, + name = recoverWalletConfig.name, + network = recoverWalletConfig.network.intoProto(), + scriptType = ActiveWalletScriptType.P2WPKH, + descriptor = descriptor.toStringWithSecret(), + changeDescriptor = changeDescriptor.toStringWithSecret(), + recoveryPhrase = mnemonicString + ) // TODO: launch this correctly, not on the main thread // Save the new wallet to the datastore - runBlocking { userPreferencesRepository.updateActiveWallets(newWalletForDatastore) } + runBlocking { walletRepository.addWallet(newWalletForDatastore) } val bdkWallet = BdkWallet( @@ -342,7 +339,7 @@ class Wallet private constructor( connection = connection, fullScanCompleted = false, walletId = walletId, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, internalAppFilesPath = internalAppFilesPath, network = recoverWalletConfig.network ) @@ -359,7 +356,7 @@ fun createScriptAppropriateDescriptor( ActiveWalletScriptType.P2WPKH -> Descriptor.newBip84(bip32ExtendedRootKey, keychain, NetworkKind.TEST) ActiveWalletScriptType.P2TR -> Descriptor.newBip86(bip32ExtendedRootKey, keychain, NetworkKind.TEST) ActiveWalletScriptType.UNKNOWN -> TODO() - ActiveWalletScriptType.UNRECOGNIZED -> TODO() + // ActiveWalletScriptType.UNRECOGNIZED -> TODO() } } diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt new file mode 100644 index 0000000..8c9e204 --- /dev/null +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/WalletRepository.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2021-2026 thunderbiscuit and contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the ./LICENSE file. + */ + +package org.bitcoindevkit.devkitwallet.domain + +import androidx.datastore.core.DataStore +import kotlinx.coroutines.flow.first +import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet +import org.bitcoindevkit.devkitwallet.data.datastore.WalletData + +class WalletRepository(private val store: DataStore) { + suspend fun fetchWallets() = store.data.first().wallets + + suspend fun addWallet(wallet: StoredWallet) = store.updateData { it.copy(wallets = it.wallets + wallet) } + + suspend fun setFullScanCompleted(walletId: String) = + store.updateData { data -> + data.copy( + wallets = data.wallets.map { + if (it.id == walletId) it.copy(fullScanCompleted = true) else it + } + ) + } +} diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt index 1c061ec..d8d505b 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/domain/utils/ProtobufExtensions.kt @@ -6,7 +6,7 @@ package org.bitcoindevkit.devkitwallet.domain.utils import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.ActiveWalletNetwork +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletNetwork fun Network.intoProto(): ActiveWalletNetwork { return when (this) { @@ -23,6 +23,6 @@ fun ActiveWalletNetwork.intoDomain(): Network { ActiveWalletNetwork.TESTNET -> Network.TESTNET ActiveWalletNetwork.SIGNET -> Network.SIGNET ActiveWalletNetwork.REGTEST -> Network.REGTEST - ActiveWalletNetwork.UNRECOGNIZED -> throw IllegalArgumentException("Unrecognized network") + // ActiveWalletNetwork.UNRECOGNIZED -> throw IllegalArgumentException("Unrecognized network") } } diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt index e6a2fcd..b064ded 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/DevkitWalletActivity.kt @@ -23,22 +23,29 @@ import kotlinx.coroutines.async import kotlinx.coroutines.launch import org.bitcoindevkit.devkitwallet.data.NewWalletConfig import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig -import org.bitcoindevkit.devkitwallet.data.SingleWallet -import org.bitcoindevkit.devkitwallet.data.UserPreferences -import org.bitcoindevkit.devkitwallet.data.UserPreferencesSerializer +import org.bitcoindevkit.devkitwallet.data.datastore.AppSettings +import org.bitcoindevkit.devkitwallet.data.datastore.AppSettingsSerializer +import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet +import org.bitcoindevkit.devkitwallet.data.datastore.WalletData +import org.bitcoindevkit.devkitwallet.data.datastore.WalletDataSerializer +import org.bitcoindevkit.devkitwallet.domain.AppSettingsRepository import org.bitcoindevkit.devkitwallet.domain.DwLogger import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO -import org.bitcoindevkit.devkitwallet.domain.UserPreferencesRepository import org.bitcoindevkit.devkitwallet.domain.Wallet +import org.bitcoindevkit.devkitwallet.domain.WalletRepository import org.bitcoindevkit.devkitwallet.presentation.navigation.AppNavigation import org.bitcoindevkit.devkitwallet.presentation.theme.DevkitTheme import org.bitcoindevkit.devkitwallet.presentation.theme.themeSurfaceColor import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.OnboardingScreen private const val TAG = "DevkitWalletActivity" -private val Context.userPreferencesStore: DataStore by dataStore( - fileName = "user_preferences.pb", - serializer = UserPreferencesSerializer, +private val Context.appSettingsStore: DataStore by dataStore( + fileName = "app_settings.json", + serializer = AppSettingsSerializer, +) +private val Context.walletDataStore: DataStore by dataStore( + fileName = "wallet_data.json", + serializer = WalletDataSerializer, ) class DevkitWalletActivity : ComponentActivity() { @@ -50,10 +57,11 @@ class DevkitWalletActivity : ComponentActivity() { // Initialize Devkit Wallet Logger (used in the LogsScreen) DwLogger.log(INFO, "Devkit Wallet app started") - val userPreferencesRepository = UserPreferencesRepository(userPreferencesStore) + val appSettingsRepository = AppSettingsRepository(appSettingsStore) + val walletRepository = WalletRepository(walletDataStore) var activeWallet: Wallet? by mutableStateOf(null) - var activeWallets: List by mutableStateOf(emptyList()) + var activeWallets: List by mutableStateOf(emptyList()) var onboardingDone: Boolean by mutableStateOf(false) var useDarkTheme: Boolean by mutableStateOf(true) var preferencesLoaded: Boolean by mutableStateOf(false) @@ -66,7 +74,7 @@ class DevkitWalletActivity : ComponentActivity() { Wallet.createWallet( newWalletConfig = walletCreateType.newWalletConfig, internalAppFilesPath = filesDir.absolutePath, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, ) } @@ -74,7 +82,7 @@ class DevkitWalletActivity : ComponentActivity() { Wallet.loadActiveWallet( activeWallet = walletCreateType.activeWallet, internalAppFilesPath = filesDir.absolutePath, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, ) } @@ -82,7 +90,7 @@ class DevkitWalletActivity : ComponentActivity() { Wallet.recoverWallet( recoverWalletConfig = walletCreateType.recoverWalletConfig, internalAppFilesPath = filesDir.absolutePath, - userPreferencesRepository = userPreferencesRepository, + walletRepository = walletRepository, ) } } @@ -97,23 +105,23 @@ class DevkitWalletActivity : ComponentActivity() { // include a fade-out, which causes the window background to show through briefly. // Updating it here (synchronously, before Compose recomposes) prevents a color flash. window.setBackgroundDrawable(themeSurfaceColor(useDarkTheme).toDrawable()) - lifecycleScope.launch { userPreferencesRepository.setDarkTheme(useDarkTheme) } + lifecycleScope.launch { appSettingsRepository.setDarkTheme(useDarkTheme) } } lifecycleScope.launch { activeWallets = async { - userPreferencesRepository.fetchActiveWallets() + walletRepository.fetchWallets() }.await() onboardingDone = async { - userPreferencesRepository.fetchIntroDone() + appSettingsRepository.fetchIntroDone() }.await() useDarkTheme = async { - userPreferencesRepository.fetchDarkTheme() + appSettingsRepository.fetchDarkTheme() }.await() // Set the window background before allowing the UI to render for the first time, @@ -123,7 +131,7 @@ class DevkitWalletActivity : ComponentActivity() { } val onFinishOnboarding: () -> Unit = { - lifecycleScope.launch { userPreferencesRepository.setIntroDone() } + lifecycleScope.launch { appSettingsRepository.setIntroDone() } onboardingDone = true } @@ -151,7 +159,7 @@ class DevkitWalletActivity : ComponentActivity() { sealed class WalletCreateType { data class FROMSCRATCH(val newWalletConfig: NewWalletConfig) : WalletCreateType() - data class LOADEXISTING(val activeWallet: SingleWallet) : WalletCreateType() + data class LOADEXISTING(val activeWallet: StoredWallet) : WalletCreateType() data class RECOVER(val recoverWalletConfig: RecoverWalletConfig) : WalletCreateType() } diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt index 5d1f7a6..48b1364 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/navigation/AppNavigation.kt @@ -21,7 +21,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute -import org.bitcoindevkit.devkitwallet.data.SingleWallet +import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet import org.bitcoindevkit.devkitwallet.domain.Wallet import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.ActiveWalletsScreen @@ -93,7 +93,7 @@ private val m3BackwardExit: ExitTransition = @Composable fun AppNavigation( activeWallet: Wallet?, - activeWallets: List, + activeWallets: List, onBuildWalletButtonClicked: (WalletCreateType) -> Unit, useDarkTheme: Boolean, onToggleTheme: () -> Unit, diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt index f99b1f6..b5d5c41 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/components/WalletOptionsCard.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.ActiveWalletScriptType +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.domain.supportedNetworks import org.bitcoindevkit.devkitwallet.presentation.theme.inter import org.bitcoindevkit.devkitwallet.presentation.ui.screens.intro.displayString diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt index c76c6e2..ff638d3 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/ActiveWalletsScreen.kt @@ -30,7 +30,7 @@ import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.composables.icons.lucide.ChevronRight import com.composables.icons.lucide.Lucide -import org.bitcoindevkit.devkitwallet.data.SingleWallet +import org.bitcoindevkit.devkitwallet.data.datastore.StoredWallet import org.bitcoindevkit.devkitwallet.domain.DwLogger import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO import org.bitcoindevkit.devkitwallet.presentation.WalletCreateType @@ -42,7 +42,7 @@ private const val TAG = "ActiveWalletsScreen" @Composable internal fun ActiveWalletsScreen( - activeWallets: List, + activeWallets: List, navController: NavController, onBuildWalletButtonClicked: (WalletCreateType) -> Unit, ) { diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt index 5bcf9b3..3da5792 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/CreateNewWallet.kt @@ -39,8 +39,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import org.bitcoindevkit.Network -import org.bitcoindevkit.devkitwallet.data.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.data.NewWalletConfig +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.domain.DwLogger import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO import org.bitcoindevkit.devkitwallet.domain.supportedNetworks @@ -233,7 +233,6 @@ fun ActiveWalletScriptType.displayString(): String { ActiveWalletScriptType.P2TR -> "P2TR (Taproot, BIP-86)" ActiveWalletScriptType.P2WPKH -> "P2WPKH (Native Segwit, BIP-84)" ActiveWalletScriptType.UNKNOWN -> TODO() - ActiveWalletScriptType.UNRECOGNIZED -> TODO() } } diff --git a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt index d370ab9..14e20ff 100644 --- a/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt +++ b/app/src/main/java/org/bitcoindevkit/devkitwallet/presentation/ui/screens/intro/RecoverWalletScreen.kt @@ -49,8 +49,8 @@ import org.bitcoindevkit.KeychainKind import org.bitcoindevkit.Mnemonic import org.bitcoindevkit.Network import org.bitcoindevkit.NetworkKind -import org.bitcoindevkit.devkitwallet.data.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.data.RecoverWalletConfig +import org.bitcoindevkit.devkitwallet.data.datastore.ActiveWalletScriptType import org.bitcoindevkit.devkitwallet.domain.DwLogger import org.bitcoindevkit.devkitwallet.domain.DwLogger.LogLevel.INFO import org.bitcoindevkit.devkitwallet.domain.bip39WordList diff --git a/app/src/main/proto/wallets.proto b/app/src/main/proto/wallets.proto deleted file mode 100644 index 176ee87..0000000 --- a/app/src/main/proto/wallets.proto +++ /dev/null @@ -1,33 +0,0 @@ -syntax = "proto3"; - -option java_package = "org.bitcoindevkit.devkitwallet.data"; -option java_multiple_files = true; - -message UserPreferences { - bool darkTheme = 1; - bool introDone = 2; - repeated SingleWallet wallets = 3; -} - -message SingleWallet { - string id = 1; - string name = 2; - ActiveWalletNetwork network = 3; - ActiveWalletScriptType scriptType = 4; - string descriptor = 5; - string changeDescriptor = 6; - string recoveryPhrase = 7; - bool fullScanCompleted = 8; -} - -enum ActiveWalletNetwork { - TESTNET = 0; - SIGNET = 1; - REGTEST = 2; -} - -enum ActiveWalletScriptType { - P2WPKH = 0; - P2TR = 1; - UNKNOWN = 2; -}