11package to.bitkit.repositories
22
33import android.content.Context
4+ import com.synonym.bitkitcore.migrateBackupActivitiesJson
5+ import com.synonym.bitkitcore.migrateBackupActivityTagsJson
6+ import com.synonym.bitkitcore.migrateBackupPreActivityMetadataJson
47import dagger.hilt.android.qualifiers.ApplicationContext
58import kotlinx.coroutines.CoroutineDispatcher
69import kotlinx.coroutines.CoroutineScope
@@ -26,6 +29,9 @@ import kotlinx.coroutines.launch
2629import kotlinx.coroutines.withContext
2730import kotlinx.coroutines.withTimeout
2831import kotlinx.serialization.Serializable
32+ import kotlinx.serialization.json.JsonArray
33+ import kotlinx.serialization.json.JsonObject
34+ import kotlinx.serialization.json.jsonObject
2935import to.bitkit.R
3036import to.bitkit.data.AppDb
3137import to.bitkit.data.CacheStore
@@ -558,7 +564,11 @@ class BackupRepo @Inject constructor(
558564
559565 val result = runCatching {
560566 performRestore(BackupCategory .METADATA ) { dataBytes ->
561- val parsed = json.decodeFromString<MetadataBackupV1 >(String (dataBytes))
567+ val migrated = migrateCoreOwnedBackupFields(
568+ String (dataBytes),
569+ mapOf (" tagMetadata" to ::migrateBackupPreActivityMetadataJson),
570+ )
571+ val parsed = json.decodeFromString<MetadataBackupV1 >(migrated)
562572 val cleanCache = parsed.cache.resetBip21() // Force address rotation
563573 cacheStore.update { cleanCache }
564574 Logger .debug(" Restored caches: ${jsonLogOf(parsed.cache.copy(cachedRates = emptyList()))} " , TAG )
@@ -594,7 +604,14 @@ class BackupRepo @Inject constructor(
594604 parsed.createdAt
595605 }
596606 performRestore(BackupCategory .ACTIVITY ) { dataBytes ->
597- val parsed = json.decodeFromString<ActivityBackupV1 >(String (dataBytes))
607+ val migrated = migrateCoreOwnedBackupFields(
608+ String (dataBytes),
609+ mapOf (
610+ " activities" to ::migrateBackupActivitiesJson,
611+ " activityTags" to ::migrateBackupActivityTagsJson,
612+ ),
613+ )
614+ val parsed = json.decodeFromString<ActivityBackupV1 >(migrated)
598615 activityRepo.restoreFromBackup(parsed)
599616 parsed.createdAt
600617 }
@@ -668,6 +685,28 @@ class BackupRepo @Inject constructor(
668685 }
669686 }
670687
688+ /* *
689+ * Fill in wallet ids that predate wallet-scoped activity data before a backup
690+ * envelope is decoded. Each Core-owned array field is handed to the matching
691+ * Core migration helper as raw JSON, so the app never edits Core model JSON
692+ * itself. Records that already carry a wallet id are left unchanged, so this
693+ * is safe to run on current backups too.
694+ */
695+ private fun migrateCoreOwnedBackupFields (
696+ raw : String ,
697+ fieldMigrations : Map <String , (String ) - > String >,
698+ ): String {
699+ val root = json.parseToJsonElement(raw).jsonObject
700+ val patched = root.toMutableMap()
701+ for ((field, migrate) in fieldMigrations) {
702+ val element = root[field]
703+ if (element is JsonArray ) {
704+ patched[field] = json.parseToJsonElement(migrate(element.toString()))
705+ }
706+ }
707+ return JsonObject (patched).toString()
708+ }
709+
671710 private suspend fun performRestore (
672711 category : BackupCategory ,
673712 restoreAction : suspend (dataBytes: ByteArray ) -> Long ,
0 commit comments