diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt index 7836fb25e..40e8718e6 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/details/PaymentDetailsSplashView.kt @@ -44,7 +44,6 @@ import fr.acinq.bitcoin.ByteVector32 import fr.acinq.bitcoin.TxId import fr.acinq.bitcoin.utils.Either import fr.acinq.lightning.blockchain.electrum.ElectrumConnectionStatus -import fr.acinq.lightning.blockchain.electrum.getConfirmations import fr.acinq.lightning.db.* import fr.acinq.lightning.payment.FinalFailure import fr.acinq.lightning.payment.OutgoingPaymentFailure diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/receive/ReceiveViewModel.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/receive/ReceiveViewModel.kt index 588fed26b..5ae9d0cdf 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/receive/ReceiveViewModel.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/payments/receive/ReceiveViewModel.kt @@ -38,6 +38,7 @@ import fr.acinq.phoenix.android.utils.datastore.SwapAddressFormat import fr.acinq.phoenix.android.utils.datastore.UserPrefsRepository import fr.acinq.phoenix.managers.PeerManager import fr.acinq.phoenix.managers.WalletManager +import fr.acinq.phoenix.managers.phoenixSwapInWallet import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first @@ -111,7 +112,7 @@ class ReceiveViewModel( viewModelScope.launch { val swapAddressFormat = userPrefs.getSwapAddressFormat.first() if (swapAddressFormat == SwapAddressFormat.LEGACY) { - val legacySwapInAddress = peerManager.getPeer().swapInWallet.legacySwapInAddress + val legacySwapInAddress = peerManager.getPeer().phoenixSwapInWallet.legacySwapInAddress val image = BitmapHelper.generateBitmap(legacySwapInAddress).asImageBitmap() currentSwapAddress = BitcoinAddressState.Show(0, legacySwapInAddress, image) } else { @@ -124,7 +125,7 @@ class ReceiveViewModel( log.info("starting with swap-in address $startAddress:$startIndex") // monitor the actual address from the swap-in wallet -- might take some time since the wallet must check all previous addresses - peerManager.getPeer().swapInWallet.swapInAddressFlow.filterNotNull().collect { (newAddress, newIndex) -> + peerManager.getPeer().phoenixSwapInWallet.swapInAddressFlow.filterNotNull().collect { (newAddress, newIndex) -> log.info("swap-in wallet current address update: $newAddress:$newIndex") val newImage = BitmapHelper.generateBitmap(newAddress).asImageBitmap() internalDataRepository.saveLastUsedSwapIndex(newIndex) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/services/ChannelsWatcher.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/services/ChannelsWatcher.kt index 47edd66da..d6e32562d 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/services/ChannelsWatcher.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/services/ChannelsWatcher.kt @@ -104,7 +104,7 @@ class ChannelsWatcher(context: Context, workerParams: WorkerParameters) : Corout // connect electrum (and only electrum), and wait for the watcher to catch-up withTimeout(ELECTRUM_TIMEOUT_MILLIS) { - peer.watcher.openUpToDateFlow().first() + business.electrumWatcher.openUpToDateFlow().first() } log.info("electrum watcher is up-to-date") business.appConnectionsDaemon?.decrementDisconnectCount(AppConnectionsDaemon.ControlTarget.Electrum) diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddressesViewModel.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddressesViewModel.kt index 54ef63dc1..52a99a0c4 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddressesViewModel.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/settings/walletinfo/SwapInAddressesViewModel.kt @@ -26,6 +26,7 @@ import androidx.lifecycle.viewmodel.CreationExtras import fr.acinq.lightning.blockchain.electrum.WalletState import fr.acinq.phoenix.android.PhoenixApplication import fr.acinq.phoenix.managers.PeerManager +import fr.acinq.phoenix.managers.phoenixSwapInWallet import kotlinx.coroutines.launch import org.slf4j.LoggerFactory @@ -44,7 +45,7 @@ class SwapInAddressesViewModel(private val peerManager: PeerManager) : ViewModel @UiThread private fun monitorSwapAddresses() { viewModelScope.launch { - peerManager.getPeer().swapInWallet.wallet.walletStateFlow.collect { walletState -> + peerManager.getPeer().phoenixSwapInWallet.wallet.walletStateFlow.collect { walletState -> val newAddresses = walletState.addresses.toList().sortedByDescending { val meta = it.second.meta if (meta is WalletState.AddressMeta.Derived) { diff --git a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/LegacyMigrationHelper.kt b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/LegacyMigrationHelper.kt index 95dd0d310..7687c62dd 100644 --- a/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/LegacyMigrationHelper.kt +++ b/phoenix-android/src/main/kotlin/fr/acinq/phoenix/android/utils/LegacyMigrationHelper.kt @@ -52,6 +52,7 @@ import fr.acinq.phoenix.legacy.utils.Prefs import fr.acinq.phoenix.legacy.utils.ThemeHelper import fr.acinq.phoenix.legacy.utils.Wallet import fr.acinq.phoenix.managers.AppConnectionsDaemon +import fr.acinq.phoenix.managers.phoenixSwapInWallet import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first import org.slf4j.Logger @@ -498,7 +499,7 @@ fun WalletPaymentInfo.isLegacyMigration(peer: Peer?): Boolean? { return when { p !is ChannelCloseOutgoingPayment -> false peer == null -> null - p.address == peer.swapInWallet.legacySwapInAddress && metadata.userDescription == LegacyMigrationHelper.migrationDescFlag -> true + p.address == peer.phoenixSwapInWallet.legacySwapInAddress && metadata.userDescription == LegacyMigrationHelper.migrationDescFlag -> true else -> false } } diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt index 68a428557..39a69a04b 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/PhoenixBusiness.kt @@ -78,7 +78,7 @@ class PhoenixBusiness( val chain: Chain = NodeParamsManager.chain val electrumClient by lazy { ElectrumClient(scope = MainScope(), loggerFactory = loggerFactory, pingInterval = 30.seconds, rpcTimeout = 10.seconds) } - internal val electrumWatcher by lazy { ElectrumWatcher(electrumClient, MainScope(), loggerFactory) } + val electrumWatcher by lazy { ElectrumWatcher(electrumClient, MainScope(), loggerFactory) } var appConnectionsDaemon: AppConnectionsDaemon? = null diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt index da96972e7..48833bb1d 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/controllers/config/CloseChannelsConfigurationController.kt @@ -13,6 +13,7 @@ import fr.acinq.phoenix.controllers.config.CloseChannelsConfiguration.Model.Chan import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.localBalance import fr.acinq.lightning.logging.info +import fr.acinq.phoenix.managers.phoenixFinalWallet import kotlinx.coroutines.launch class AppCloseChannelsConfigurationController( @@ -93,7 +94,7 @@ class AppCloseChannelsConfigurationController( val closableChannelsList = updatedChannelsList.filter { isClosable(it.status) } - val address = peer.finalWallet.finalAddress + val address = peer.phoenixFinalWallet.finalAddress model(CloseChannelsConfiguration.Model.Ready( channels = closableChannelsList, address = address diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt index 9edc3bbe9..ad5210416 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/BalanceManager.kt @@ -86,7 +86,7 @@ class BalanceManager( */ private suspend fun monitorSwapInBalance(peer: Peer) { val swapInParams = peer.walletParams.swapInParams - combine(peer.currentTipFlow.filterNotNull(), peer.channelsFlow, peer.swapInWallet.wallet.walletStateFlow) { (currentBlockHeight, _), channels, swapInWallet -> + combine(peer.currentTipFlow.filterNotNull(), peer.channelsFlow, peer.phoenixSwapInWallet.wallet.walletStateFlow) { currentBlockHeight, channels, swapInWallet -> val reservedInputs = SwapInManager.reservedWalletInputs(channels.values.filterIsInstance()) val walletWithoutReserved = swapInWallet.withoutReservedUtxos(reservedInputs) walletWithoutReserved.withConfirmations( diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt index b4e2497d1..95ad976c0 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PaymentsManager.kt @@ -2,7 +2,6 @@ package fr.acinq.phoenix.managers import fr.acinq.bitcoin.TxId import fr.acinq.lightning.blockchain.electrum.ElectrumClient -import fr.acinq.lightning.blockchain.electrum.getConfirmations import fr.acinq.lightning.db.InboundLiquidityOutgoingPayment import fr.acinq.lightning.db.SpliceCpfpOutgoingPayment import fr.acinq.lightning.db.WalletPayment diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt index d6c2aa596..df288d83a 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/managers/PeerManager.kt @@ -11,7 +11,11 @@ import fr.acinq.lightning.SwapInParams import fr.acinq.lightning.TrampolineFees import fr.acinq.lightning.UpgradeRequired import fr.acinq.lightning.WalletParams +import fr.acinq.lightning.blockchain.electrum.ElectrumClient import fr.acinq.lightning.blockchain.electrum.ElectrumWatcher +import fr.acinq.lightning.blockchain.electrum.FinalWallet +import fr.acinq.lightning.blockchain.electrum.IElectrumClient +import fr.acinq.lightning.blockchain.electrum.SwapInWallet import fr.acinq.lightning.blockchain.electrum.WalletState import fr.acinq.lightning.blockchain.fee.FeeratePerKw import fr.acinq.lightning.channel.states.ChannelStateWithCommitments @@ -42,6 +46,7 @@ class PeerManager( private val databaseManager: DatabaseManager, private val configurationManager: AppConfigurationManager, private val notificationsManager: NotificationsManager, + private val electrumClient: ElectrumClient, private val electrumWatcher: ElectrumWatcher, ) : CoroutineScope by CoroutineScope(CoroutineName("peer") + SupervisorJob() + Dispatchers.Main + CoroutineExceptionHandler { _, e -> println("error in Peer coroutine scope: ${e.message}") @@ -55,6 +60,7 @@ class PeerManager( databaseManager = business.databaseManager, configurationManager = business.appConfigurationManager, notificationsManager = business.notificationsManager, + electrumClient = business.electrumClient, electrumWatcher = business.electrumWatcher, ) @@ -77,7 +83,7 @@ class PeerManager( /** Flow of the peer's final wallet [WalletState.WalletWithConfirmations]. */ @OptIn(ExperimentalCoroutinesApi::class) val finalWallet = peerState.filterNotNull().flatMapLatest { peer -> - combine(peer.currentTipFlow.filterNotNull(), peer.finalWallet.wallet.walletStateFlow) { (currentBlockHeight, _), wallet -> + combine(peer.currentTipFlow.filterNotNull(), peer.phoenixFinalWallet.wallet.walletStateFlow) { currentBlockHeight, wallet -> wallet.withConfirmations( currentBlockHeight = currentBlockHeight, // the final wallet does not need to distinguish between weak/deep/locked txs @@ -97,7 +103,7 @@ class PeerManager( /** Flow of the peer's swap-in wallet [WalletState.WalletWithConfirmations]. */ @OptIn(ExperimentalCoroutinesApi::class) val swapInWallet = peerState.filterNotNull().flatMapLatest { peer -> - combine(peer.currentTipFlow.filterNotNull(), peer.swapInWallet.wallet.walletStateFlow) { (currentBlockHeight, _), wallet -> + combine(peer.currentTipFlow.filterNotNull(), peer.phoenixSwapInWallet.wallet.walletStateFlow) { currentBlockHeight, wallet -> wallet.withConfirmations( currentBlockHeight = currentBlockHeight, swapInParams = peer.walletParams.swapInParams @@ -175,6 +181,7 @@ class PeerManager( initTlvStream = initTlvs, nodeParams = nodeParams, walletParams = walletParams, + client = electrumClient, watcher = electrumWatcher, db = databaseManager.databases.filterNotNull().first(), trustedSwapInTxs = startupParams.trustedSwapInTxs, @@ -256,3 +263,12 @@ class PeerManager( } } } + + +/** The peer's swap-in wallet for Phoenix is always not null, because the client is always an [IElectrumClient] (see how this Peer is built in `PeerManager.init`). */ +val Peer.phoenixSwapInWallet: SwapInWallet + get() = this.swapInWallet!! + +/** The peer's final wallet for Phoenix is always not null, because the client is always an [IElectrumClient] (see how this Peer is built in `PeerManager.init`). */ +val Peer.phoenixFinalWallet: FinalWallet + get() = this.finalWallet!! diff --git a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt index 4b50411b0..0ee265a98 100644 --- a/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt +++ b/phoenix-shared/src/commonMain/kotlin/fr.acinq.phoenix/utils/migrations/IosMigrationHelper.kt @@ -33,6 +33,7 @@ import fr.acinq.phoenix.utils.Parser import fr.acinq.phoenix.utils.extensions.isBeingCreated import fr.acinq.lightning.logging.info import fr.acinq.lightning.logging.warning +import fr.acinq.phoenix.managers.phoenixSwapInWallet import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first @@ -89,7 +90,7 @@ object IosMigrationHelper { val log = loggerFactory.newLogger(this::class) val peer = peerManager.getPeer() - val swapInAddress = peer.swapInWallet.swapInAddressFlow.filterNotNull().first().first + val swapInAddress = peer.phoenixSwapInWallet.swapInAddressFlow.filterNotNull().first().first val closingScript = Parser.addressToPublicKeyScriptOrNull(chain, swapInAddress) if (closingScript == null) { log.warning { "aborting: could not get a valid closing script" } @@ -139,7 +140,7 @@ object IosMigrationHelper { log.info { "${closingTxs.size} channels closed to ${closingScript.toHex()}" } // Wait for all UTXOs to arrive in swap-in wallet. - peer.swapInWallet.wallet.walletStateFlow + peer.phoenixSwapInWallet.wallet.walletStateFlow .map { it.utxos.map { it.outPoint.txid } } .first { txidsInWallet -> closingTxs.values.all { txid -> txidsInWallet.contains(txid) } } log.info { "all mutual-close txids found in swap-in wallet" }