@@ -90,6 +90,7 @@ class MigrationService @Inject constructor(
9090 private const val RN_PENDING_METADATA_KEY = " rnPendingMetadata"
9191 private const val RN_PENDING_TRANSFERS_KEY = " rnPendingTransfers"
9292 private const val RN_PENDING_BOOSTS_KEY = " rnPendingBoosts"
93+ private const val RN_DID_ATTEMPT_PEER_RECOVERY_KEY = " rnDidAttemptMigrationPeerRecovery"
9394 private const val OPENING_CURLY_BRACE = " {"
9495 private const val MMKV_ROOT = " persist:root"
9596 private const val RN_WALLET_NAME = " wallet0"
@@ -1251,6 +1252,44 @@ class MigrationService @Inject constructor(
12511252 Logger .info(" RN migration completed, marked for post-migration sync" , context = TAG )
12521253 }
12531254
1255+ private suspend fun isRnMigrationCompleted (): Boolean {
1256+ val key = stringPreferencesKey(RN_MIGRATION_COMPLETED_KEY )
1257+ return rnMigrationStore.data.first()[key] == " true"
1258+ }
1259+
1260+ private suspend fun didAttemptPeerRecovery (): Boolean {
1261+ val key = stringPreferencesKey(RN_DID_ATTEMPT_PEER_RECOVERY_KEY )
1262+ return rnMigrationStore.data.first()[key] == " true"
1263+ }
1264+
1265+ private suspend fun setDidAttemptPeerRecovery () {
1266+ val key = stringPreferencesKey(RN_DID_ATTEMPT_PEER_RECOVERY_KEY )
1267+ rnMigrationStore.edit { it[key] = " true" }
1268+ }
1269+
1270+ suspend fun tryFetchMigrationPeersFromBackup (): List <String > {
1271+ if (! isRnMigrationCompleted()) return emptyList()
1272+ if (didAttemptPeerRecovery()) return emptyList()
1273+
1274+ setDidAttemptPeerRecovery()
1275+
1276+ return runCatching {
1277+ val data = rnBackupClient.retrieve(" peers" , fileGroup = " ldk" ) ? : return emptyList()
1278+ val peers = json.decodeFromString<List <BackupPeerEntry >>(String (data))
1279+ if (peers.isEmpty()) return emptyList()
1280+
1281+ val trustedIds = Env .trustedLnPeers.map { it.nodeId }.toSet()
1282+ val uris = peers
1283+ .filter { it.pubKey !in trustedIds }
1284+ .map { " ${it.pubKey} @${it.address} :${it.port} " }
1285+
1286+ Logger .info(" Migration peer recovery: fetched ${uris.size} peer(s) from remote backup" , context = TAG )
1287+ uris
1288+ }.onFailure {
1289+ Logger .warn(" Migration peer recovery failed (will not retry)" , it, context = TAG )
1290+ }.getOrDefault(emptyList())
1291+ }
1292+
12541293 suspend fun cleanupAfterMigration () {
12551294 clearPersistedMigrationData()
12561295 setNeedsPostMigrationSync(false )
@@ -2076,6 +2115,13 @@ data class RNWidgetsWithOptions(
20762115 val widgetOptions : Map <String , ByteArray >,
20772116)
20782117
2118+ @Serializable
2119+ data class BackupPeerEntry (
2120+ val pubKey : String ,
2121+ val address : String ,
2122+ val port : UShort ,
2123+ )
2124+
20792125private val Context .rnMigrationDataStore: DataStore <Preferences > by preferencesDataStore(" rn_migration" )
20802126private val Context .rnKeychainDataStore: DataStore <Preferences > by preferencesDataStore(" RN_KEYCHAIN" )
20812127
0 commit comments