From 441ad2569060e475bb866ff7c3f0b398068ae7c8 Mon Sep 17 00:00:00 2001 From: HashEngineering Date: Tue, 14 May 2024 10:54:16 -0700 Subject: [PATCH] feat(dashpay): support upgrades over Dash Wallet for database and wallet (#1282) * fix: handle database migration from Dash Wallet --- .../wallet/database/DatabaseMigrationTest.kt | 3 +- .../19.json | 854 ++++++++++++++++++ .../schildbach/wallet/database/AppDatabase.kt | 3 +- .../wallet/database/AppDatabaseMigrations.kt | 9 +- .../database/entity/BlockchainIdentityData.kt | 6 - .../de/schildbach/wallet/di/DatabaseModule.kt | 3 +- .../wallet/service/WalletFactory.kt | 2 + .../wallet/ui/OnboardingViewModel.kt | 1 + .../schildbach/wallet/ui/main/MainActivity.kt | 19 + .../wallet/ui/main/MainViewModel.kt | 5 + 10 files changed, 894 insertions(+), 11 deletions(-) create mode 100644 wallet/schemas/de.schildbach.wallet.database.AppDatabase/19.json diff --git a/wallet/androidTest/de/schildbach/wallet/database/DatabaseMigrationTest.kt b/wallet/androidTest/de/schildbach/wallet/database/DatabaseMigrationTest.kt index 8cd4fb607d..78445dcc03 100644 --- a/wallet/androidTest/de/schildbach/wallet/database/DatabaseMigrationTest.kt +++ b/wallet/androidTest/de/schildbach/wallet/database/DatabaseMigrationTest.kt @@ -61,7 +61,8 @@ open class DatabaseMigrationTest { private val migrations = arrayOf( AppDatabaseMigrations.migration11To12, AppDatabaseMigrations.migration12To17, - AppDatabaseMigrations.migration17To18 + AppDatabaseMigrations.migration17To18, + AppDatabaseMigrations.migration18To19 ) @Rule diff --git a/wallet/schemas/de.schildbach.wallet.database.AppDatabase/19.json b/wallet/schemas/de.schildbach.wallet.database.AppDatabase/19.json new file mode 100644 index 0000000000..e61f91875d --- /dev/null +++ b/wallet/schemas/de.schildbach.wallet.database.AppDatabase/19.json @@ -0,0 +1,854 @@ +{ + "formatVersion": 1, + "database": { + "version": 19, + "identityHash": "252c929aa2815002b443b105fd586c9d", + "entities": [ + { + "tableName": "exchange_rates", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`currencyCode` TEXT NOT NULL, `rate` TEXT, PRIMARY KEY(`currencyCode`))", + "fields": [ + { + "fieldPath": "currencyCode", + "columnName": "currencyCode", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "currencyCode" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "blockchain_state", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`bestChainDate` INTEGER, `bestChainHeight` INTEGER NOT NULL, `replaying` INTEGER NOT NULL, `impediments` TEXT NOT NULL, `chainlockHeight` INTEGER NOT NULL, `mnlistHeight` INTEGER NOT NULL, `percentageSync` INTEGER NOT NULL, `id` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "bestChainDate", + "columnName": "bestChainDate", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "bestChainHeight", + "columnName": "bestChainHeight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "replaying", + "columnName": "replaying", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "impediments", + "columnName": "impediments", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "chainlockHeight", + "columnName": "chainlockHeight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "mnlistHeight", + "columnName": "mnlistHeight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "percentageSync", + "columnName": "percentageSync", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "transaction_metadata", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`txId` BLOB NOT NULL, `timestamp` INTEGER NOT NULL, `value` INTEGER NOT NULL, `type` TEXT NOT NULL, `taxCategory` TEXT, `currencyCode` TEXT, `rate` TEXT, `memo` TEXT NOT NULL, `service` TEXT, `customIconId` BLOB, PRIMARY KEY(`txId`))", + "fields": [ + { + "fieldPath": "txId", + "columnName": "txId", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "taxCategory", + "columnName": "taxCategory", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "currencyCode", + "columnName": "currencyCode", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "memo", + "columnName": "memo", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "service", + "columnName": "service", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customIconId", + "columnName": "customIconId", + "affinity": "BLOB", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "txId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "address_metadata", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`address` TEXT NOT NULL, `isInput` INTEGER NOT NULL, `taxCategory` TEXT NOT NULL, `service` TEXT NOT NULL, PRIMARY KEY(`address`, `isInput`))", + "fields": [ + { + "fieldPath": "address", + "columnName": "address", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isInput", + "columnName": "isInput", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "taxCategory", + "columnName": "taxCategory", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "service", + "columnName": "service", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "address", + "isInput" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "icon_bitmaps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` BLOB NOT NULL, `imageData` BLOB NOT NULL, `originalUrl` TEXT NOT NULL, `height` INTEGER NOT NULL, `width` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "imageData", + "columnName": "imageData", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "originalUrl", + "columnName": "originalUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "height", + "columnName": "height", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "width", + "columnName": "width", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "gift_cards", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`txId` BLOB NOT NULL, `merchantName` TEXT NOT NULL, `price` REAL NOT NULL, `number` TEXT, `pin` TEXT, `barcodeValue` TEXT, `barcodeFormat` TEXT, `merchantUrl` TEXT, `note` TEXT, PRIMARY KEY(`txId`))", + "fields": [ + { + "fieldPath": "txId", + "columnName": "txId", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "merchantName", + "columnName": "merchantName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "price", + "columnName": "price", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "number", + "columnName": "number", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "pin", + "columnName": "pin", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "barcodeValue", + "columnName": "barcodeValue", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "barcodeFormat", + "columnName": "barcodeFormat", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "merchantUrl", + "columnName": "merchantUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "note", + "columnName": "note", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "txId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "dashpay_profile", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `username` TEXT NOT NULL, `displayName` TEXT NOT NULL, `publicMessage` TEXT NOT NULL, `avatarUrl` TEXT NOT NULL, `avatarHash` BLOB, `avatarFingerprint` BLOB, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`userId`))", + "fields": [ + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "displayName", + "columnName": "displayName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "publicMessage", + "columnName": "publicMessage", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "avatarUrl", + "columnName": "avatarUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "avatarHash", + "columnName": "avatarHash", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "avatarFingerprint", + "columnName": "avatarFingerprint", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "userId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "dashpay_contact_request", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `toUserId` TEXT NOT NULL, `accountReference` INTEGER NOT NULL, `encryptedPublicKey` BLOB NOT NULL, `senderKeyIndex` INTEGER NOT NULL, `recipientKeyIndex` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `encryptedAccountLabel` BLOB, `autoAcceptProof` BLOB, PRIMARY KEY(`userId`, `toUserId`, `accountReference`))", + "fields": [ + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "toUserId", + "columnName": "toUserId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "accountReference", + "columnName": "accountReference", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "encryptedPublicKey", + "columnName": "encryptedPublicKey", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "senderKeyIndex", + "columnName": "senderKeyIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "recipientKeyIndex", + "columnName": "recipientKeyIndex", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "encryptedAccountLabel", + "columnName": "encryptedAccountLabel", + "affinity": "BLOB", + "notNull": false + }, + { + "fieldPath": "autoAcceptProof", + "columnName": "autoAcceptProof", + "affinity": "BLOB", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "userId", + "toUserId", + "accountReference" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "user_alerts", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`stringResId` INTEGER NOT NULL, `iconResId` INTEGER NOT NULL, `dismissed` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, PRIMARY KEY(`stringResId`))", + "fields": [ + { + "fieldPath": "stringResId", + "columnName": "stringResId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "iconResId", + "columnName": "iconResId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "dismissed", + "columnName": "dismissed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "stringResId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "invitation_table", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`userId` TEXT NOT NULL, `txid` BLOB NOT NULL, `createdAt` INTEGER NOT NULL, `memo` TEXT NOT NULL, `sentAt` INTEGER NOT NULL, `acceptedAt` INTEGER NOT NULL, `shortDynamicLink` TEXT, `dynamicLink` TEXT, PRIMARY KEY(`userId`))", + "fields": [ + { + "fieldPath": "userId", + "columnName": "userId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "txid", + "columnName": "txid", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "memo", + "columnName": "memo", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "sentAt", + "columnName": "sentAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "acceptedAt", + "columnName": "acceptedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "shortDynamicLink", + "columnName": "shortDynamicLink", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "dynamicLink", + "columnName": "dynamicLink", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "userId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "transaction_metadata_cache", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`cacheTimestamp` INTEGER NOT NULL, `txId` BLOB NOT NULL, `sentTimestamp` INTEGER, `taxCategory` TEXT, `currencyCode` TEXT, `rate` TEXT, `memo` TEXT, `service` TEXT, `customIconUrl` TEXT, `giftCardNumber` TEXT, `giftCardPin` TEXT, `merchantName` TEXT, `originalPrice` REAL, `barcodeValue` TEXT, `barcodeFormat` TEXT, `merchantUrl` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "fields": [ + { + "fieldPath": "cacheTimestamp", + "columnName": "cacheTimestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "txId", + "columnName": "txId", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "sentTimestamp", + "columnName": "sentTimestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "taxCategory", + "columnName": "taxCategory", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "currencyCode", + "columnName": "currencyCode", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "memo", + "columnName": "memo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "service", + "columnName": "service", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customIconUrl", + "columnName": "customIconUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "giftCardNumber", + "columnName": "giftCardNumber", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "giftCardPin", + "columnName": "giftCardPin", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "merchantName", + "columnName": "merchantName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "originalPrice", + "columnName": "originalPrice", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "barcodeValue", + "columnName": "barcodeValue", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "barcodeFormat", + "columnName": "barcodeFormat", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "merchantUrl", + "columnName": "merchantUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "transaction_metadata_platform", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `timestamp` INTEGER NOT NULL, `txId` BLOB NOT NULL, `sentTimestamp` INTEGER, `taxCategory` TEXT, `currencyCode` TEXT, `rate` REAL, `memo` TEXT, `service` TEXT, `customIconUrl` TEXT, `giftCardNumber` TEXT, `giftCardPin` TEXT, `merchantName` TEXT, `originalPrice` REAL, `barcodeValue` TEXT, `barcodeFormat` TEXT, `merchantUrl` TEXT, PRIMARY KEY(`id`, `txId`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "txId", + "columnName": "txId", + "affinity": "BLOB", + "notNull": true + }, + { + "fieldPath": "sentTimestamp", + "columnName": "sentTimestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "taxCategory", + "columnName": "taxCategory", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "currencyCode", + "columnName": "currencyCode", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "rate", + "columnName": "rate", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "memo", + "columnName": "memo", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "service", + "columnName": "service", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "customIconUrl", + "columnName": "customIconUrl", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "giftCardNumber", + "columnName": "giftCardNumber", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "giftCardPin", + "columnName": "giftCardPin", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "merchantName", + "columnName": "merchantName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "originalPrice", + "columnName": "originalPrice", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "barcodeValue", + "columnName": "barcodeValue", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "barcodeFormat", + "columnName": "barcodeFormat", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "merchantUrl", + "columnName": "merchantUrl", + "affinity": "TEXT", + "notNull": false + } + ], + "primaryKey": { + "columnNames": [ + "id", + "txId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "username_requests", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`requestId` TEXT NOT NULL, `username` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `identity` TEXT NOT NULL, `link` TEXT, `votes` INTEGER NOT NULL, `isApproved` INTEGER NOT NULL, PRIMARY KEY(`requestId`))", + "fields": [ + { + "fieldPath": "requestId", + "columnName": "requestId", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "username", + "columnName": "username", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "identity", + "columnName": "identity", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "link", + "columnName": "link", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "votes", + "columnName": "votes", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isApproved", + "columnName": "isApproved", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "requestId" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '252c929aa2815002b443b105fd586c9d')" + ] + } +} \ No newline at end of file diff --git a/wallet/src/de/schildbach/wallet/database/AppDatabase.kt b/wallet/src/de/schildbach/wallet/database/AppDatabase.kt index 55dbe2d567..3ef5950a83 100644 --- a/wallet/src/de/schildbach/wallet/database/AppDatabase.kt +++ b/wallet/src/de/schildbach/wallet/database/AppDatabase.kt @@ -58,7 +58,6 @@ import org.dash.wallet.common.data.entity.GiftCard AddressMetadata::class, IconBitmap::class, GiftCard::class, - BlockchainIdentityData::class, DashPayProfile::class, DashPayContactRequest::class, UserAlert::class, @@ -67,7 +66,7 @@ import org.dash.wallet.common.data.entity.GiftCard TransactionMetadataDocument::class, UsernameRequest::class ], - version = 18 // if increasing version, we need migrations to preserve tx/addr metadata + version = 19 // if increasing version, we need migrations to preserve tx/addr metadata ) @TypeConverters(RoomConverters::class, BlockchainStateRoomConverters::class) abstract class AppDatabase : RoomDatabase() { diff --git a/wallet/src/de/schildbach/wallet/database/AppDatabaseMigrations.kt b/wallet/src/de/schildbach/wallet/database/AppDatabaseMigrations.kt index 58ef50ea0f..cfc9323cef 100644 --- a/wallet/src/de/schildbach/wallet/database/AppDatabaseMigrations.kt +++ b/wallet/src/de/schildbach/wallet/database/AppDatabaseMigrations.kt @@ -88,11 +88,18 @@ class AppDatabaseMigrations { ) database.execSQL( - "CREATE TABLE IF NOT EXISTS username_requests (`requestId` TEXT PRIMARY KEY," + + "CREATE TABLE IF NOT EXISTS username_requests (`requestId` TEXT NOT NULL PRIMARY KEY," + "`username` TEXT NOT NULL, `createdAt` INTEGER NOT NULL, `identity` TEXT NOT NULL," + "`link` TEXT, `votes` INTEGER NOT NULL, `isApproved` INTEGER NOT NULL);" ) } } + val migration18To19 = object : Migration(18, 19) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + "DROP TABLE IF EXISTS `blockchain_identity`" + ) + } + } } } diff --git a/wallet/src/de/schildbach/wallet/database/entity/BlockchainIdentityData.kt b/wallet/src/de/schildbach/wallet/database/entity/BlockchainIdentityData.kt index a560b3b356..63891ba6b7 100644 --- a/wallet/src/de/schildbach/wallet/database/entity/BlockchainIdentityData.kt +++ b/wallet/src/de/schildbach/wallet/database/entity/BlockchainIdentityData.kt @@ -23,9 +23,6 @@ import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.room.Entity -import androidx.room.Ignore -import androidx.room.PrimaryKey import de.schildbach.wallet.data.InvitationLinkData import de.schildbach.wallet.service.CoinJoinMode import de.schildbach.wallet.service.platform.PlatformService @@ -47,7 +44,6 @@ import org.dashj.platform.dpp.util.Converters import javax.inject.Inject import javax.inject.Singleton -@Entity(tableName = "blockchain_identity") data class BlockchainIdentityData(var creationState: CreationState = CreationState.NONE, var creationStateErrorMessage: String?, var username: String?, @@ -68,13 +64,11 @@ data class BlockchainIdentityData(var creationState: CreationState = CreationSta var currentMainKeyIndex: Int? = null, var currentMainKeyType: IdentityPublicKey.Type? = null) { - @PrimaryKey var id = 1 set(@Suppress("UNUSED_PARAMETER") value) { field = 1 } - @Ignore private var creditFundingTransactionCache: AssetLockTransaction? = null fun findAssetLockTransaction(wallet: Wallet?): AssetLockTransaction? { diff --git a/wallet/src/de/schildbach/wallet/di/DatabaseModule.kt b/wallet/src/de/schildbach/wallet/di/DatabaseModule.kt index fb5027b8dd..41231d3bce 100644 --- a/wallet/src/de/schildbach/wallet/di/DatabaseModule.kt +++ b/wallet/src/de/schildbach/wallet/di/DatabaseModule.kt @@ -41,7 +41,8 @@ object DatabaseModule { AppDatabaseMigrations.migration11To12, AppDatabaseMigrations.migration12To17, AppDatabaseMigrations.migration16To17, - AppDatabaseMigrations.migration17To18 + AppDatabaseMigrations.migration17To18, + AppDatabaseMigrations.migration18To19 ) // destructive migrations are used from versions 1 to 11 .fallbackToDestructiveMigration() diff --git a/wallet/src/de/schildbach/wallet/service/WalletFactory.kt b/wallet/src/de/schildbach/wallet/service/WalletFactory.kt index 353063b17b..7ae887fc86 100644 --- a/wallet/src/de/schildbach/wallet/service/WalletFactory.kt +++ b/wallet/src/de/schildbach/wallet/service/WalletFactory.kt @@ -168,6 +168,8 @@ class DashWalletFactory @Inject constructor( // does this work on encrypted backups? wallet.addKeyChain(Constants.BIP44_PATH) + wallet as WalletEx + wallet.initializeCoinJoin(0) return wallet } finally { try { diff --git a/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt b/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt index cdac2c7dea..c4d869bdfc 100644 --- a/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/OnboardingViewModel.kt @@ -78,6 +78,7 @@ class OnboardingViewModel @Inject constructor( if (!walletApplication.isWalletUpgradedToBIP44) { walletApplication.wallet!!.addKeyChain(Constants.BIP44_PATH) } + (walletApplication.wallet as WalletEx).initializeCoinJoin(0) configuration.armBackupSeedReminder() finishUnecryptedWalletUpgradeAction.call(Unit) diff --git a/wallet/src/de/schildbach/wallet/ui/main/MainActivity.kt b/wallet/src/de/schildbach/wallet/ui/main/MainActivity.kt index 4506cbb1ed..18fa899f5e 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/MainActivity.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/MainActivity.kt @@ -65,7 +65,9 @@ import de.schildbach.wallet_test.R import de.schildbach.wallet_test.databinding.ActivityMainBinding import kotlinx.coroutines.launch import org.bitcoinj.crypto.ChildNumber +import org.bitcoinj.wallet.DerivationPathFactory import org.bitcoinj.wallet.Wallet +import org.bitcoinj.wallet.WalletEx import org.dash.wallet.common.Configuration import org.dash.wallet.common.ui.BaseAlertDialogBuilder import org.dash.wallet.common.ui.FancyAlertDialog @@ -147,6 +149,7 @@ class MainActivity : AbstractBindServiceActivity(), ActivityCompat.OnRequestPerm if (savedInstanceState == null) { // Add BIP44 support and PIN if missing upgradeWalletKeyChains(Constants.BIP44_PATH, false) + upgradeWalletCoinJoin(false) } viewModel.currencyChangeDetected.observe( @@ -351,6 +354,7 @@ class MainActivity : AbstractBindServiceActivity(), ActivityCompat.OnRequestPerm getSharedPreferences(Constants.WALLET_LOCK_PREFS_NAME, Context.MODE_PRIVATE).edit().clear().commit() config.disarmBackupReminder() upgradeWalletKeyChains(Constants.BIP44_PATH, true) + upgradeWalletCoinJoin(true) } private fun handleInvite(invite: InvitationLinkData) { @@ -543,6 +547,21 @@ class MainActivity : AbstractBindServiceActivity(), ActivityCompat.OnRequestPerm } } + open fun upgradeWalletCoinJoin(restoreBackup: Boolean) { + val wallet = walletData.wallet!! + isRestoringBackup = restoreBackup + val coinJoinPath = DerivationPathFactory(Constants.NETWORK_PARAMETERS).coinJoinDerivationPath(0) + if ((wallet as WalletEx).coinJoin != null && !wallet.coinJoin.hasKeyChain(coinJoinPath)) { + if (wallet.isEncrypted()) { + viewModel.addCoinJoinToWallet() + } + } else { + if (restoreBackup) { + checkRestoredWalletEncryptionDialog() + } else checkWalletEncryptionDialog() + } + } + private fun showBackupWalletDialogIfNeeded() { if (showBackupWalletDialog) { BackupWalletDialogFragment.show(this) diff --git a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt index c761f07cf1..7aa3693337 100644 --- a/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt +++ b/wallet/src/de/schildbach/wallet/ui/main/MainViewModel.kt @@ -701,4 +701,9 @@ class MainViewModel @Inject constructor( AnalyticsConstants.Process.PROCESS_CONTACT_REQUEST_RECEIVE ) } + + fun addCoinJoinToWallet() { + val encryptionKey = platformRepo.getWalletEncryptionKey() ?: throw IllegalStateException("cannot obtain wallet encryption key") + (walletApplication.wallet as WalletEx).initializeCoinJoin(encryptionKey, 0) + } }