From 5dc4f5a0b522805e99eb0e52a3e38b315ad9bb2d Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 19:29:16 +0100 Subject: [PATCH 01/19] refactor: reorg env and rename props --- .../java/to/bitkit/services/TxBumpingTests.kt | 9 +- app/src/main/java/to/bitkit/env/Env.kt | 152 ++++++++------- .../main/java/to/bitkit/ext/PeerDetails.kt | 6 +- app/src/main/java/to/bitkit/fcm/FcmService.kt | 4 +- .../to/bitkit/repositories/BlocktankRepo.kt | 2 +- .../to/bitkit/repositories/LightningRepo.kt | 24 +-- .../to/bitkit/services/LightningService.kt | 178 ++++++++---------- .../services/LspNotificationsService.kt | 4 +- .../main/java/to/bitkit/ui/NodeInfoScreen.kt | 2 +- .../ui/screens/transfer/FundingScreen.kt | 4 +- .../external/ExternalConnectionScreen.kt | 4 +- .../external/ExternalNodeViewModel.kt | 4 +- .../transfer/external/LnurlChannelScreen.kt | 2 +- .../external/LnurlChannelViewModel.kt | 4 +- .../send/SendCoinSelectionViewModel.kt | 6 +- .../CustomFeeSettingsScreen.kt | 4 +- .../ui/sheets/BoostTransactionViewModel.kt | 4 +- .../java/to/bitkit/viewmodels/AppViewModel.kt | 6 +- .../to/bitkit/viewmodels/LdkDebugViewModel.kt | 4 +- .../java/to/bitkit/ext/PeerDetailsTest.kt | 8 +- .../bitkit/repositories/LightningRepoTest.kt | 10 +- .../java/to/bitkit/ui/WalletViewModelTest.kt | 4 +- .../test/java/to/bitkit/utils/CryptoTest.kt | 6 +- 23 files changed, 211 insertions(+), 240 deletions(-) diff --git a/app/src/androidTest/java/to/bitkit/services/TxBumpingTests.kt b/app/src/androidTest/java/to/bitkit/services/TxBumpingTests.kt index d698f9a1a..e46347f45 100644 --- a/app/src/androidTest/java/to/bitkit/services/TxBumpingTests.kt +++ b/app/src/androidTest/java/to/bitkit/services/TxBumpingTests.kt @@ -138,9 +138,10 @@ class TxBumpingTests { assertEquals(depositAmount, totalBalance, "Balance should equal deposit amount") // Send a transaction with a low fee rate + @Suppress("SpellCheckingInspection") val destinationAddress = "bcrt1qs04g2ka4pr9s3mv73nu32tvfy7r3cxd27wkyu8" val sendAmount = 10_000uL // Send 10,000 sats - val lowFeeRate = 1u // 1 sat/vbyte (very low) + val lowFeeRate = 1uL // 1 sat/vbyte (very low) println("Sending $sendAmount sats to $destinationAddress with low fee rate of $lowFeeRate sat/vbyte") val originalTxId = lightningService.send( @@ -160,7 +161,7 @@ class TxBumpingTests { println("Wait completed") // Bump the fee using RBF with a higher fee rate - val highFeeRate = 10u // 10 sat/vbyte (much higher) + val highFeeRate = 10uL // 10 sat/vbyte (much higher) println("Bumping fee for transaction $originalTxId to $highFeeRate sat/vbyte using RBF") val replacementTxId = lightningService.bumpFeeByRbf( @@ -261,7 +262,7 @@ class TxBumpingTests { // Now use CPFP to spend from the incoming transaction with high fees // This demonstrates using CPFP to quickly move received funds - val highFeeRate = 20u // 20 sat/vbyte (very high for fast confirmation) + val highFeeRate = 20uL // 20 sat/vbyte (very high for fast confirmation) println("Using CPFP to quickly spend from incoming transaction $stuckIncomingTxId with $highFeeRate sat/vbyte") // Generate a destination address for the CPFP transaction (where we'll send the funds) @@ -272,7 +273,7 @@ class TxBumpingTests { val childTxId = lightningService.accelerateByCpfp( txid = stuckIncomingTxId, satsPerVByte = highFeeRate, - destinationAddress = cpfpDestinationAddress, + toAddress = cpfpDestinationAddress, ) assertFalse(childTxId.isEmpty(), "CPFP child transaction ID should not be empty") diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 30e815741..2fbbb680a 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -6,18 +6,18 @@ import org.lightningdevkit.ldknode.Network import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.BuildConfig import to.bitkit.ext.ensureDir -import to.bitkit.ext.parse +import to.bitkit.ext.of import to.bitkit.models.BlocktankNotificationType import to.bitkit.utils.Logger import java.io.File import kotlin.io.path.Path -@Suppress("ConstPropertyName", "KotlinConstantConditions") +@Suppress("ConstPropertyName", "KotlinConstantConditions", "SimplifyBooleanWithConstants") internal object Env { val isDebug = BuildConfig.DEBUG const val isE2eTest = BuildConfig.E2E const val isGeoblockingEnabled = BuildConfig.GEO - private val e2eBackend = BuildConfig.E2E_BACKEND.lowercase() + val e2eBackend = BuildConfig.E2E_BACKEND.lowercase() val network = Network.valueOf(BuildConfig.NETWORK) val locales = BuildConfig.LOCALES.split(",") val walletSyncIntervalSecs = 10_uL // TODO review @@ -28,25 +28,18 @@ internal object Env { val trustedLnPeers get() = when (network) { - Network.BITCOIN -> listOf(Peers.mainnetLnd1, Peers.mainnetLnd3, Peers.mainnetLnd4) - Network.REGTEST -> listOf(Peers.staging) - Network.TESTNET -> listOf(Peers.staging) - else -> emptyList() + Network.BITCOIN -> listOf(Peers.lnd1, Peers.lnd3, Peers.lnd4) + Network.REGTEST -> listOf(Peers.stag) + Network.TESTNET -> listOf(Peers.stag) + else -> listOf() } - const val fxRateRefreshInterval: Long = 2 * 60 * 1000 // 2 minutes in milliseconds - const val fxRateStaleThreshold: Long = 10 * 60 * 1000 // 10 minutes in milliseconds + const val fxRateRefreshInterval = 2 * 60 * 1000L // 2 minutes in millis + const val fxRateStaleThreshold = 10 * 60 * 1000L // 10 minutes in millis + const val lspOrdersRefreshInterval = 2 * 60 * 1000L // 2 minutes in millis - const val blocktankOrderRefreshInterval: Long = 2 * 60 * 1000 // 2 minutes in milliseconds - - val pushNotificationFeatures = listOf( - BlocktankNotificationType.incomingHtlc, - BlocktankNotificationType.mutualClose, - BlocktankNotificationType.orderPaymentConfirmed, - BlocktankNotificationType.cjitPaymentArrived, - BlocktankNotificationType.wakeToTimeout, - ) - const val DERIVATION_NAME = "bitkit-notifications" + val pushNotificationFeatures = BlocktankNotificationType.entries + const val derivationName = "bitkit-notifications" const val FILE_PROVIDER_AUTHORITY = "${BuildConfig.APPLICATION_ID}.fileprovider" const val SUPPORT_EMAIL = "support@synonym.to" @@ -54,56 +47,15 @@ internal object Env { const val PIN_LENGTH = 4 const val PIN_ATTEMPTS = 8 - // region File Paths - - private lateinit var appStoragePath: String - - fun initAppStoragePath(path: String) { - require(path.isNotBlank()) { "App storage path cannot be empty." } - appStoragePath = path - Logger.info("App storage path: $path") - } - - val logDir: File - get() { - require(::appStoragePath.isInitialized) - return File(appStoragePath).resolve("logs").ensureDir() - } - - fun ldkStoragePath(walletIndex: Int) = storagePathOf(walletIndex, network.name.lowercase(), "ldk") - - fun bitkitCoreStoragePath(walletIndex: Int): String { - return storagePathOf(walletIndex, network.name.lowercase(), "core") - } - - /** - * Generates the storage path for a specified wallet index, network, and directory. - * - * Output format: - * - * `appStoragePath/network/walletN/dir` - */ - private fun storagePathOf(walletIndex: Int, network: String, dir: String): String { - require(::appStoragePath.isInitialized) { "App storage path should be 'context.filesDir.absolutePath'." } - val path = Path(appStoragePath, network, "wallet$walletIndex", dir) - .toFile() - .ensureDir() - .path - Logger.debug("Using ${dir.uppercase()} storage path: $path") - return path - } - - // endregion - - // region Server URLs + // region urls val electrumServerUrl: String get() { - if (isE2eTest && e2eBackend == "local") return ElectrumServers.E2E + if (isE2eTest && e2eBackend == "local") return ElectrumServers.REGTEST.LOCAL return when (network) { - Network.REGTEST -> ElectrumServers.REGTEST + Network.REGTEST -> ElectrumServers.REGTEST.STAGING Network.TESTNET -> ElectrumServers.TESTNET - Network.BITCOIN -> ElectrumServers.BITCOIN + Network.BITCOIN -> ElectrumServers.MAINNET.FULCRUM else -> TODO("${network.name} network not implemented") } } @@ -201,11 +153,52 @@ internal object Env { } // endregion + + // region paths + + private lateinit var appStoragePath: String + + fun initAppStoragePath(path: String) { + require(path.isNotBlank()) { "App storage path cannot be empty." } + appStoragePath = path + Logger.info("App storage path: $path") + } + + val logDir: File + get() { + require(::appStoragePath.isInitialized) + return File(appStoragePath).resolve("logs").ensureDir() + } + + fun ldkStoragePath(walletIndex: Int) = storagePathOf(walletIndex, network.name.lowercase(), "ldk") + + fun bitkitCoreStoragePath(walletIndex: Int): String { + return storagePathOf(walletIndex, network.name.lowercase(), "core") + } + + /** + * Generates the storage path for a specified wallet index, network, and directory. + * + * Output format: + * + * `appStoragePath/network/walletN/dir` + */ + private fun storagePathOf(walletIndex: Int, network: String, dir: String): String { + require(::appStoragePath.isInitialized) { "App storage path should be 'context.filesDir.absolutePath'." } + val path = Path(appStoragePath, network, "wallet$walletIndex", dir) + .toFile() + .ensureDir() + .path + Logger.debug("Using ${dir.uppercase()} storage path: $path") + return path + } + + // endregion } @Suppress("ConstPropertyName") -object TransactionDefaults { - /** Total recommended tx base fee in sats */ +object Defaults { + /** Recommended transaction base fee in sats */ const val recommendedBaseFee = 256u /** @@ -213,22 +206,27 @@ object TransactionDefaults { * required to include them in a block would be greater than the value of the transaction itself. * */ const val dustLimit = 546u + + } object Peers { - val staging = - PeerDetails.parse("028a8910b0048630d4eb17af25668cdd7ea6f2d8ae20956e7a06e2ae46ebcb69fc@34.65.86.104:9400") - val mainnetLnd1 = - PeerDetails.parse("039b8b4dd1d88c2c5db374290cda397a8f5d79f312d6ea5d5bfdfc7c6ff363eae3@34.65.111.104:9735") - val mainnetLnd3 = - PeerDetails.parse("03816141f1dce7782ec32b66a300783b1d436b19777e7c686ed00115bd4b88ff4b@34.65.191.64:9735") - val mainnetLnd4 = - PeerDetails.parse("02a371038863605300d0b3fc9de0cf5ccb57728b7f8906535709a831b16e311187@34.65.186.40:9735") + val stag = PeerDetails.of("028a8910b0048630d4eb17af25668cdd7ea6f2d8ae20956e7a06e2ae46ebcb69fc@34.65.86.104:9400") + val lnd1 = PeerDetails.of("039b8b4dd1d88c2c5db374290cda397a8f5d79f312d6ea5d5bfdfc7c6ff363eae3@34.65.111.104:9735") + val lnd3 = PeerDetails.of("03816141f1dce7782ec32b66a300783b1d436b19777e7c686ed00115bd4b88ff4b@34.65.191.64:9735") + val lnd4 = PeerDetails.of("02a371038863605300d0b3fc9de0cf5ccb57728b7f8906535709a831b16e311187@34.65.186.40:9735") } private object ElectrumServers { - const val BITCOIN = "ssl://fulcrum.bitkit.blocktank.to:8900" + object MAINNET { + const val FULCRUM = "ssl://fulcrum.bitkit.blocktank.to:8900" + const val ESPLORA = "ssl://34.65.252.32:18484" + } + + object REGTEST { + const val STAGING = "tcp://34.65.252.32:18483" + const val LOCAL = "tcp://127.0.0.1:60001" + } + const val TESTNET = "ssl://electrum.blockstream.info:60002" - const val REGTEST = "tcp://34.65.252.32:18483" - const val E2E = "tcp://127.0.0.1:60001" } diff --git a/app/src/main/java/to/bitkit/ext/PeerDetails.kt b/app/src/main/java/to/bitkit/ext/PeerDetails.kt index cb419a395..6ed4e5543 100644 --- a/app/src/main/java/to/bitkit/ext/PeerDetails.kt +++ b/app/src/main/java/to/bitkit/ext/PeerDetails.kt @@ -9,7 +9,8 @@ val PeerDetails.port get() = address.substringAfter(":") val PeerDetails.uri get() = "$nodeId@$address" -fun PeerDetails.Companion.parse(uri: String): PeerDetails { +/*** Creates a [PeerDetails] object from a URI string.*/ +fun PeerDetails.Companion.of(uri: String): PeerDetails { val parts = uri.split("@") require(parts.size == 2) { "Invalid uri format, expected: '@:', got: '$uri'" } @@ -30,7 +31,8 @@ fun PeerDetails.Companion.parse(uri: String): PeerDetails { ) } -fun PeerDetails.Companion.from(nodeId: String, host: String, port: String) = PeerDetails( +/*** Creates a [PeerDetails] object from a node ID, host, and port.*/ +fun PeerDetails.Companion.of(nodeId: String, host: String, port: String) = PeerDetails( nodeId = nodeId, address = "$host:$port", isConnected = false, diff --git a/app/src/main/java/to/bitkit/fcm/FcmService.kt b/app/src/main/java/to/bitkit/fcm/FcmService.kt index a9ab62d45..b37a7e655 100644 --- a/app/src/main/java/to/bitkit/fcm/FcmService.kt +++ b/app/src/main/java/to/bitkit/fcm/FcmService.kt @@ -14,7 +14,7 @@ import kotlinx.serialization.SerializationException import kotlinx.serialization.json.JsonObject import to.bitkit.data.keychain.Keychain import to.bitkit.di.json -import to.bitkit.env.Env.DERIVATION_NAME +import to.bitkit.env.Env.derivationName import to.bitkit.ext.fromBase64 import to.bitkit.ext.fromHex import to.bitkit.models.BlocktankNotificationType @@ -105,7 +105,7 @@ class FcmService : FirebaseMessagingService() { return } val password = - runCatching { crypto.generateSharedSecret(privateKey, response.publicKey, DERIVATION_NAME) }.getOrElse { + runCatching { crypto.generateSharedSecret(privateKey, response.publicKey, derivationName) }.getOrElse { Logger.error("Failed to generate shared secret", it, context = TAG) return } diff --git a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt index 59fa2ebc0..aa007bbe3 100644 --- a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt @@ -88,7 +88,7 @@ class BlocktankRepo @Inject constructor( flow { while (currentCoroutineContext().isActive) { emit(Unit) - delay(Env.blocktankOrderRefreshInterval) + delay(Env.lspOrdersRefreshInterval) } }.flowOn(bgDispatcher) .onEach { refreshOrders() } diff --git a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt index 2b350d488..80fb68be6 100644 --- a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt @@ -671,9 +671,9 @@ class LightningRepo @Inject constructor( require(address.isNotEmpty()) { "Send address cannot be empty" } val transactionSpeed = speed ?: settingsStore.data.first().defaultTransactionSpeed - val satsPerVByte = getFeeRateForSpeed(transactionSpeed, feeRates).getOrThrow().toUInt() + val satsPerVByte = getFeeRateForSpeed(transactionSpeed, feeRates).getOrThrow() - // if utxos are manually specified, use them, otherwise run auto coin select if enabled + // use passed utxos if specified, otherwise run auto coin select if enabled val finalUtxosToSpend = utxosToSpend ?: determineUtxosToSpend( sats = sats, satsPerVByte = satsPerVByte, @@ -697,7 +697,7 @@ class LightningRepo @Inject constructor( txId = txId, address = address, isReceive = false, - feeRate = satsPerVByte.toULong(), + feeRate = satsPerVByte, isTransfer = isTransfer, channelId = channelId ?: "", ) @@ -709,7 +709,7 @@ class LightningRepo @Inject constructor( suspend fun determineUtxosToSpend( sats: ULong, - satsPerVByte: UInt, + satsPerVByte: ULong, ): List? = withContext(bgDispatcher) { return@withContext runCatching { val settings = settingsStore.data.first() @@ -767,7 +767,7 @@ class LightningRepo @Inject constructor( ): Result = withContext(bgDispatcher) { return@withContext try { val transactionSpeed = speed ?: settingsStore.data.first().defaultTransactionSpeed - val satsPerVByte = getFeeRateForSpeed(transactionSpeed, feeRates).getOrThrow().toUInt() + val satsPerVByte = getFeeRateForSpeed(transactionSpeed, feeRates).getOrThrow() val addressOrDefault = address ?: cacheStore.data.first().onchainAddress @@ -905,22 +905,18 @@ class LightningRepo @Inject constructor( suspend fun bumpFeeByRbf( originalTxId: Txid, - satsPerVByte: UInt, + satsPerVByte: ULong, ): Result = executeWhenNodeRunning("bumpFeeByRbf") { try { if (originalTxId.isBlank()) { return@executeWhenNodeRunning Result.failure( - IllegalArgumentException( - "originalTxId is null or empty: $originalTxId" - ) + IllegalArgumentException("originalTxId is null or empty: $originalTxId") ) } if (satsPerVByte <= 0u) { return@executeWhenNodeRunning Result.failure( - IllegalArgumentException( - "satsPerVByte invalid: $satsPerVByte" - ) + IllegalArgumentException("satsPerVByte invalid: $satsPerVByte") ) } @@ -944,7 +940,7 @@ class LightningRepo @Inject constructor( suspend fun accelerateByCpfp( originalTxId: Txid, - satsPerVByte: UInt, + satsPerVByte: ULong, destinationAddress: Address, ): Result = executeWhenNodeRunning("accelerateByCpfp") { try { @@ -969,7 +965,7 @@ class LightningRepo @Inject constructor( val newDestinationTxId = lightningService.accelerateByCpfp( txid = originalTxId, satsPerVByte = satsPerVByte, - destinationAddress = destinationAddress, + toAddress = destinationAddress, ) Logger.debug( "accelerateByCpfp success, newDestinationTxId: $newDestinationTxId originalTxId: $originalTxId, satsPerVByte: $satsPerVByte destinationAddress: $destinationAddress" diff --git a/app/src/main/java/to/bitkit/services/LightningService.kt b/app/src/main/java/to/bitkit/services/LightningService.kt index ecf919925..00f130aab 100644 --- a/app/src/main/java/to/bitkit/services/LightningService.kt +++ b/app/src/main/java/to/bitkit/services/LightningService.kt @@ -73,7 +73,7 @@ class LightningService @Inject constructor( private val _syncStatusChanged = MutableSharedFlow(extraBufferCapacity = 1) val syncStatusChanged: SharedFlow = _syncStatusChanged.asSharedFlow() - private var trustedPeers: List = Env.trustedLnPeers + private lateinit var trustedPeers: List suspend fun setup( walletIndex: Int, @@ -82,7 +82,7 @@ class LightningService @Inject constructor( trustedPeers: List? = null, channelMigration: ChannelDataMigration? = null, ) { - Logger.debug("Building node…") + Logger.debug("Building node…", context = TAG) val config = config(walletIndex, trustedPeers) node = build( @@ -93,7 +93,7 @@ class LightningService @Inject constructor( channelMigration, ) - Logger.info("LDK node setup") + Logger.info("LDK node setup", context = TAG) } private fun config( @@ -102,11 +102,10 @@ class LightningService @Inject constructor( ): Config { val dirPath = Env.ldkStoragePath(walletIndex) - trustedPeers?.takeIf { it.isNotEmpty() }?.let { - this.trustedPeers = it - } ?: run { - Logger.info("Using fallback trusted peers from Env (${Env.trustedLnPeers.size})", context = TAG) + this.trustedPeers = trustedPeers?.takeIf { it.isNotEmpty() } ?: Env.trustedLnPeers.also { + Logger.warn("Missing trusted peers from LSP, falling back to preconfigured env peers", context = TAG) } + val trustedPeerNodeIds = this.trustedPeers.map { it.nodeId } return defaultConfig().copy( @@ -152,7 +151,8 @@ class LightningService @Inject constructor( val lnurlAuthServerUrl = Env.lnurlAuthServerUrl val fixedHeaders = emptyMap() Logger.verbose( - "Building ldk-node with \n\t vssUrl: '$vssUrl'\n\t lnurlAuthServerUrl: '$lnurlAuthServerUrl'" + "Building node with \n\t vssUrl: '$vssUrl'\n\t lnurlAuthServerUrl: '$lnurlAuthServerUrl'", + context = TAG, ) if (lnurlAuthServerUrl.isNotEmpty()) { builder.buildWithVssStore(vssUrl, vssStoreId, lnurlAuthServerUrl, fixedHeaders) @@ -169,17 +169,17 @@ class LightningService @Inject constructor( private suspend fun Builder.configureGossipSource(customRgsServerUrl: String?) { val rgsServerUrl = customRgsServerUrl ?: settingsStore.data.first().rgsServerUrl if (rgsServerUrl != null) { - Logger.info("Using gossip source: RGS server '$rgsServerUrl'") + Logger.info("Using gossip source: RGS server '$rgsServerUrl'", context = TAG) setGossipSourceRgs(rgsServerUrl) } else { - Logger.info("Using gossip source: P2P") + Logger.info("Using gossip source: P2P", context = TAG) setGossipSourceP2p() } } private suspend fun Builder.configureChainSource(customServerUrl: String? = null) { val serverUrl = customServerUrl ?: settingsStore.data.first().electrumServer - Logger.info("Using onchain source Electrum Sever url: $serverUrl") + Logger.info("Using onchain source Electrum Sever url: $serverUrl", context = TAG) setChainSourceElectrum( serverUrl = serverUrl, config = ElectrumSyncConfig( @@ -195,7 +195,7 @@ class LightningService @Inject constructor( suspend fun start(timeout: Duration? = null, onEvent: NodeEventHandler? = null) { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.debug("Starting node…") + Logger.debug("Starting node…", context = TAG) ServiceQueue.LDK.background { try { @@ -210,26 +210,26 @@ class LightningService @Inject constructor( shouldListenForEvents = true launch { try { - Logger.debug("LDK event listener started") + Logger.debug("LDK event listener started", context = TAG) if (timeout != null) { withTimeout(timeout) { listenForEvents(eventHandler) } } else { listenForEvents(eventHandler) } } catch (e: Exception) { - Logger.error("LDK event listener error", e) + Logger.error("LDK event listener error", e, context = TAG) } } } - Logger.info("Node started") + Logger.info("Node started", context = TAG) } suspend fun stop() { shouldListenForEvents = false val node = this.node ?: throw ServiceError.NodeNotStarted - Logger.debug("Stopping node…") + Logger.debug("Stopping node…", context = TAG) ServiceQueue.LDK.background { try { node.stop() @@ -239,47 +239,28 @@ class LightningService @Inject constructor( this@LightningService.node = null } } - Logger.info("Node stopped") + Logger.info("Node stopped", context = TAG) } fun wipeStorage(walletIndex: Int) { if (node != null) throw ServiceError.NodeStillRunning - Logger.warn("Wiping lightning storage…") + Logger.warn("Wiping LDK storage…", context = TAG) Path(Env.ldkStoragePath(walletIndex)).toFile().deleteRecursively() - Logger.info("Lightning wallet wiped") + Logger.info("LDK storage wiped", context = TAG) } suspend fun sync() { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.verbose("Syncing LDK…") + Logger.verbose("Syncing LDK…", context = TAG) ServiceQueue.LDK.background { node.syncWallets() - // launch { setMaxDustHtlcExposureForCurrentChannels() } } _syncStatusChanged.tryEmit(Unit) - Logger.debug("LDK synced") - } - - // private fun setMaxDustHtlcExposureForCurrentChannels() { - // if (Env.network != Network.REGTEST) { - // Logger.debug("Not updating channel config for non-regtest network") - // return - // } - // val node = this.node ?: throw ServiceError.NodeNotStarted - // runCatching { - // for (channel in node.listChannels()) { - // val config = channel.config - // config.maxDustHtlcExposure = MaxDustHtlcExposure.FixedLimit(limitMsat = 999_999_UL * 1000u) - // node.updateChannelConfig(channel.userChannelId, channel.counterpartyNodeId, config) - // Logger.info("Updated channel config for: ${channel.userChannelId}") - // } - // }.onFailure { - // Logger.error("Failed to update channel config", it) - // } - // } + Logger.debug("LDK synced", context = TAG) + } suspend fun sign(message: String): String { val node = this.node ?: throw ServiceError.NodeNotSetup @@ -306,9 +287,9 @@ class LightningService @Inject constructor( for (peer in trustedPeers) { try { node.connect(peer.nodeId, peer.address, persist = true) - Logger.info("Connected to trusted peer: $peer") + Logger.info("Connected to trusted peer: $peer", context = TAG) } catch (e: NodeException) { - Logger.error("Peer connect error: $peer", LdkError(e)) + Logger.error("Peer connect error: $peer", LdkError(e), context = TAG) } } @@ -321,13 +302,13 @@ class LightningService @Inject constructor( val trustedConnected = trustedPeers.count { it.nodeId in connectedPeerIds } if (trustedConnected == 0 && trustedPeers.isNotEmpty()) { - Logger.warn("No trusted peers connected, falling back to Env peers", context = TAG) + Logger.warn("No trusted peers connected, falling back to preconfigured env peers", context = TAG) for (peer in Env.trustedLnPeers) { try { node.connect(peer.nodeId, peer.address, persist = true) - Logger.info("Connected to fallback peer: $peer") + Logger.info("Connected to fallback peer: $peer", context = TAG) } catch (e: NodeException) { - Logger.error("Fallback peer connect error: $peer", LdkError(e)) + Logger.error("Fallback peer connect error: $peer", LdkError(e), context = TAG) } } } else { @@ -340,16 +321,16 @@ class LightningService @Inject constructor( val uri = peer.uri return ServiceQueue.LDK.background { try { - Logger.debug("Connecting peer: $uri") + Logger.debug("Connecting peer: $uri", context = TAG) node.connect(peer.nodeId, peer.address, persist = true) - Logger.info("Peer connected: $uri") + Logger.info("Peer connected: $uri", context = TAG) Result.success(Unit) } catch (e: NodeException) { val error = LdkError(e) - Logger.error("Peer connect error: $uri", error) + Logger.error("Peer connect error: $uri", error, context = TAG) Result.failure(error) } } @@ -358,14 +339,14 @@ class LightningService @Inject constructor( suspend fun disconnectPeer(peer: PeerDetails) { val node = this.node ?: throw ServiceError.NodeNotSetup val uri = peer.uri - Logger.debug("Disconnecting peer: $uri") + Logger.debug("Disconnecting peer: $uri", context = TAG) try { ServiceQueue.LDK.background { node.disconnect(peer.nodeId) } - Logger.info("Peer disconnected: $uri") + Logger.info("Peer disconnected: $uri", context = TAG) } catch (e: NodeException) { - Logger.warn("Peer disconnect error: $uri", LdkError(e)) + Logger.warn("Peer disconnect error: $uri", LdkError(e), context = TAG) } } @@ -389,7 +370,7 @@ class LightningService @Inject constructor( return ServiceQueue.LDK.background { try { val pushToCounterpartyMsat = pushToCounterpartySats?.let { it * 1000u } - Logger.debug("Initiating channel open (sats: $channelAmountSats) with peer: ${peer.uri}") + Logger.debug("Initiating channel open (sats: '$channelAmountSats') with: '${peer.uri}'", context = TAG) val userChannelId = node.openChannel( peer.nodeId, @@ -407,12 +388,12 @@ class LightningService @Inject constructor( channelConfig, ) - Logger.info("Channel open initiated, result: $result") + Logger.info("Channel open initiated, result: $result", context = TAG) Result.success(result) } catch (e: NodeException) { val error = LdkError(e) - Logger.error("Error initiating channel open", error) + Logger.error("Error initiating channel open", error, context = TAG) Result.failure(error) } } @@ -449,12 +430,12 @@ class LightningService @Inject constructor( fun canReceive(): Boolean { val channels = this.channels if (channels == null) { - Logger.warn("canReceive = false: Channels not available") + Logger.warn("canReceive = false: Channels not available", context = TAG) return false } if (channels.none { it.isChannelReady }) { - Logger.warn("canReceive = false: Found no LN channel ready to enable receive: $channels") + Logger.warn("canReceive = false: Found no LN channel ready to enable receive: '$channels'", context = TAG) return false } @@ -489,14 +470,14 @@ class LightningService @Inject constructor( fun canSend(amountSats: ULong): Boolean { val channels = this.channels if (channels == null) { - Logger.warn("Channels not available") + Logger.warn("Channels not available", context = TAG) return false } val totalNextOutboundHtlcLimitSats = channels.totalNextOutboundHtlcLimitSats() if (totalNextOutboundHtlcLimitSats < amountSats) { - Logger.warn("Insufficient outbound capacity: $totalNextOutboundHtlcLimitSats < $amountSats") + Logger.warn("Insufficient outbound capacity: $totalNextOutboundHtlcLimitSats < $amountSats", context = TAG) return false } @@ -506,26 +487,29 @@ class LightningService @Inject constructor( suspend fun send( address: Address, sats: ULong, - satsPerVByte: UInt, + satsPerVByte: ULong, utxosToSpend: List? = null, isMaxAmount: Boolean = false, ): Txid { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.info("Sending $sats sats to $address, satsPerVByte=$satsPerVByte, isMaxAmount = $isMaxAmount") + Logger.info( + "Sending $sats sats to $address, satsPerVByte=$satsPerVByte, isMaxAmount = $isMaxAmount", + context = TAG, + ) return ServiceQueue.LDK.background { if (isMaxAmount) { node.onchainPayment().sendAllToAddress( address = address, retainReserve = true, - feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte.toULong()), + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), ) } else { node.onchainPayment().sendToAddress( address = address, amountSats = sats, - feeRate = convertVByteToKwu(satsPerVByte), + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), utxosToSpend = utxosToSpend, ) } @@ -535,7 +519,7 @@ class LightningService @Inject constructor( suspend fun send(bolt11: String, sats: ULong? = null): PaymentId { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.debug("Paying bolt11: $bolt11") + Logger.debug("Paying bolt11: $bolt11", context = TAG) val bolt11Invoice = runCatching { Bolt11Invoice.fromStr(bolt11) } .getOrElse { e -> throw LdkError(e as NodeException) } @@ -606,7 +590,7 @@ class LightningService @Inject constructor( suspend fun selectUtxosWithAlgorithm( targetAmountSats: ULong, - satsPerVByte: UInt, + satsPerVByte: ULong, algorithm: CoinSelectionAlgorithm, utxos: List?, ): Result> { @@ -616,7 +600,7 @@ class LightningService @Inject constructor( return@background try { val result = node.onchainPayment().selectUtxosWithAlgorithm( targetAmountSats = targetAmountSats, - feeRate = convertVByteToKwu(satsPerVByte), + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), algorithm = algorithm, utxos = utxos, ) @@ -631,16 +615,16 @@ class LightningService @Inject constructor( // endregion // region boost - suspend fun bumpFeeByRbf(txid: Txid, satsPerVByte: UInt): Txid { + suspend fun bumpFeeByRbf(txid: Txid, satsPerVByte: ULong): Txid { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.info("Bumping fee for tx $txid with satsPerVByte=$satsPerVByte") + Logger.info("RBF for txid='$txid' using satsPerVByte='$satsPerVByte'", context = TAG) return ServiceQueue.LDK.background { return@background try { node.onchainPayment().bumpFeeByRbf( txid = txid, - feeRate = convertVByteToKwu(satsPerVByte), + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), ) } catch (e: NodeException) { throw LdkError(e) @@ -650,19 +634,19 @@ class LightningService @Inject constructor( suspend fun accelerateByCpfp( txid: Txid, - satsPerVByte: UInt, - destinationAddress: Address, + satsPerVByte: ULong, + toAddress: Address, ): Txid { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.info("Accelerating tx $txid by CPFP, satsPerVByte=$satsPerVByte, destinationAddress=$destinationAddress") + Logger.info("CPFP for txid='$txid' using satsPerVByte='$satsPerVByte', to address='$toAddress'", context = TAG) return ServiceQueue.LDK.background { return@background try { node.onchainPayment().accelerateByCpfp( txid = txid, - feeRate = convertVByteToKwu(satsPerVByte), - destinationAddress = destinationAddress, + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), + destinationAddress = toAddress, ) } catch (e: NodeException) { throw LdkError(e) @@ -675,7 +659,7 @@ class LightningService @Inject constructor( suspend fun calculateCpfpFeeRate(parentTxid: Txid): FeeRate { val node = this.node ?: throw ServiceError.NodeNotSetup - Logger.info("Calculating CPFP fee for parentTxid $parentTxid") + Logger.debug("Calculating CPFP fee for parentTxid $parentTxid", context = TAG) return ServiceQueue.LDK.background { return@background try { @@ -692,13 +676,14 @@ class LightningService @Inject constructor( suspend fun calculateTotalFee( address: Address, amountSats: ULong, - satsPerVByte: UInt, + satsPerVByte: ULong, utxosToSpend: List? = null, ): ULong { val node = this.node ?: throw ServiceError.NodeNotSetup Logger.verbose( - "Calculating fee for $amountSats sats to $address, UTXOs=${utxosToSpend?.size}, satsPerVByte=$satsPerVByte" + "Calculating fee for $amountSats sats to $address, ${utxosToSpend?.size} UTXOs, satsPerVByte=$satsPerVByte", + context = TAG, ) return ServiceQueue.LDK.background { @@ -706,10 +691,13 @@ class LightningService @Inject constructor( val fee = node.onchainPayment().calculateTotalFee( address = address, amountSats = amountSats, - feeRate = convertVByteToKwu(satsPerVByte), + feeRate = FeeRate.fromSatPerVbUnchecked(satsPerVByte), utxosToSpend = utxosToSpend, ) - Logger.verbose("Calculated fee=$fee for $amountSats sats to $address, satsPerVByte=$satsPerVByte") + Logger.debug( + "Calculated fee='$fee' for $amountSats sats to $address, satsPerVByte=$satsPerVByte", + context = TAG, + ) fee } catch (e: NodeException) { throw LdkError(e) @@ -724,16 +712,16 @@ class LightningService @Inject constructor( suspend fun listenForEvents(onEvent: NodeEventHandler? = null) = withContext(bgDispatcher) { while (shouldListenForEvents) { val node = this@LightningService.node ?: let { - Logger.error(ServiceError.NodeNotStarted.message.orEmpty()) + Logger.error(ServiceError.NodeNotStarted.message.orEmpty(), context = TAG) return@withContext } val event = node.nextEventAsync() - Logger.debug("LDK-node event fired: ${jsonLogOf(event)}") + Logger.debug("LDK event fired: ${jsonLogOf(event)}", context = TAG) try { node.eventHandled() - Logger.verbose("LDK-node eventHandled: $event") + Logger.verbose("LDK eventHandled: '$event'", context = TAG) } catch (e: NodeException) { - Logger.verbose("LDK eventHandled error: $event", LdkError(e)) + Logger.verbose("LDK eventHandled error: '$event'", LdkError(e), context = TAG) } onEvent?.invoke(event) } @@ -771,6 +759,7 @@ class LightningService @Inject constructor( Logger.error("Node not available for network graph dump", context = TAG) return } + val nodeIdPreviewLength = 20 val sb = StringBuilder() sb.appendLine("\n\n=== ROUTE NOT FOUND - NETWORK GRAPH DUMP ===\n") @@ -830,7 +819,7 @@ class LightningService @Inject constructor( sb.appendLine(" Total peers: ${peers.size}") peers.forEachIndexed { index, peer -> - sb.appendLine(" Peer ${index + 1}: ${peer.nodeId.take(NODE_ID_PREVIEW_LENGTH)}... @ ${peer.address}") + sb.appendLine(" Peer ${index + 1}: ${peer.nodeId.take(nodeIdPreviewLength)}... @ ${peer.address}") sb.appendLine(" - Connected: ${peer.isConnected}, Persisted: ${peer.isPersisted}") } @@ -873,15 +862,15 @@ class LightningService @Inject constructor( val nodeId = peer.nodeId if (allNodes.any { it == nodeId }) { foundTrustedNodes++ - sb.appendLine(" OK: ${nodeId.take(NODE_ID_PREVIEW_LENGTH)}... found in graph") + sb.appendLine(" OK: ${nodeId.take(nodeIdPreviewLength)}... found in graph") } else { - sb.appendLine(" MISSING: ${nodeId.take(NODE_ID_PREVIEW_LENGTH)}... NOT in graph") + sb.appendLine(" MISSING: ${nodeId.take(nodeIdPreviewLength)}... NOT in graph") } } sb.appendLine(" Summary: $foundTrustedNodes/${trustedPeers.size} trusted peers found in graph") // Show first 10 nodes - val nodesToShow = minOf(NETWORK_GRAPH_PREVIEW_LIMIT, allNodes.size) + val nodesToShow = minOf(10, allNodes.size) sb.appendLine("\n First $nodesToShow nodes:") allNodes.take(nodesToShow).forEachIndexed { index, nodeId -> sb.appendLine(" ${index + 1}. $nodeId") @@ -940,8 +929,6 @@ class LightningService @Inject constructor( companion object { private const val TAG = "LightningService" - private const val NODE_ID_PREVIEW_LENGTH = 20 - private const val NETWORK_GRAPH_PREVIEW_LIMIT = 10 } } @@ -951,16 +938,3 @@ data class NetworkGraphInfo( val channelCount: Int, val latestRgsSyncTimestamp: ULong?, ) - -// region helpers -/** - * TODO remove, replace all usages with [FeeRate.fromSatPerVbUnchecked] - * */ -@Deprecated("replace all usages with [FeeRate.fromSatPerVbUnchecked]") -private fun convertVByteToKwu(satsPerVByte: UInt): FeeRate { - // 1 vbyte = 4 weight units, so 1 sats/vbyte = 250 sats/kwu - val satPerKwu = satsPerVByte.toULong() * 250u - // Ensure we're above the minimum relay fee - return FeeRate.fromSatPerKwu(maxOf(satPerKwu, 253u)) // FEERATE_FLOOR_SATS_PER_KW is 253 in LDK -} -// endregion diff --git a/app/src/main/java/to/bitkit/services/LspNotificationsService.kt b/app/src/main/java/to/bitkit/services/LspNotificationsService.kt index d29e8b95b..08215384a 100644 --- a/app/src/main/java/to/bitkit/services/LspNotificationsService.kt +++ b/app/src/main/java/to/bitkit/services/LspNotificationsService.kt @@ -7,7 +7,7 @@ import to.bitkit.data.keychain.Keychain import to.bitkit.data.keychain.Keychain.Key import to.bitkit.di.BgDispatcher import to.bitkit.env.Env -import to.bitkit.env.Env.DERIVATION_NAME +import to.bitkit.env.Env.derivationName import to.bitkit.ext.nowTimestamp import to.bitkit.ext.toHex import to.bitkit.utils.Crypto @@ -29,7 +29,7 @@ class LspNotificationsService @Inject constructor( Logger.debug("Registering device for notifications…") val timestamp = nowTimestamp() - val messageToSign = "$DERIVATION_NAME$deviceToken$timestamp" + val messageToSign = "$derivationName$deviceToken$timestamp" val signature = lightningService.sign(messageToSign) diff --git a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt index 320165885..d79765303 100644 --- a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt +++ b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt @@ -489,7 +489,7 @@ private fun PreviewDevMode() { latestPathfindingScoresSyncTimestamp = null, ), nodeId = "0348a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", - peers = listOf(Peers.staging), + peers = listOf(Peers.stag), channels = listOf( createChannelDetails().copy( channelId = "abc123def456789012345678901234567890123456789012345678901234567890", diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/FundingScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/FundingScreen.kt index 82d50b63f..b2e806b47 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/FundingScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/FundingScreen.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import to.bitkit.R -import to.bitkit.env.TransactionDefaults +import to.bitkit.env.Defaults import to.bitkit.ui.LocalBalances import to.bitkit.ui.components.BodyM import to.bitkit.ui.components.BodyMB @@ -45,7 +45,7 @@ fun FundingScreen( ) { val balances = LocalBalances.current val canTransfer = remember(balances.totalOnchainSats) { - balances.totalOnchainSats >= TransactionDefaults.recommendedBaseFee + balances.totalOnchainSats >= Defaults.recommendedBaseFee } var showNoFundsAlert by remember { mutableStateOf(false) } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt index 5d45f2430..fcc0a07f7 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt @@ -35,7 +35,7 @@ import androidx.lifecycle.SavedStateHandle import kotlinx.coroutines.flow.filterNotNull import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.R -import to.bitkit.ext.from +import to.bitkit.ext.of import to.bitkit.ext.getClipboardText import to.bitkit.ext.host import to.bitkit.ext.port @@ -220,7 +220,7 @@ private fun ExternalConnectionContent( ) PrimaryButton( text = stringResource(R.string.common__continue), - onClick = { onContinueClick(PeerDetails.from(nodeId = nodeId, host = host, port = port)) }, + onClick = { onContinueClick(PeerDetails.of(nodeId = nodeId, host = host, port = port)) }, enabled = isValid, isLoading = uiState.isLoading, modifier = Modifier diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt index 6c3e0924e..3e6c6479e 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalNodeViewModel.kt @@ -18,7 +18,7 @@ import org.lightningdevkit.ldknode.UserChannelId import to.bitkit.R import to.bitkit.data.SettingsStore import to.bitkit.ext.WatchResult -import to.bitkit.ext.parse +import to.bitkit.ext.of import to.bitkit.ext.watchUntil import to.bitkit.models.Toast import to.bitkit.models.TransactionSpeed @@ -84,7 +84,7 @@ class ExternalNodeViewModel @Inject constructor( fun parseNodeUri(uriString: String) { viewModelScope.launch { - val result = runCatching { PeerDetails.parse(uriString) } + val result = runCatching { PeerDetails.of(uriString) } if (result.isSuccess) { _uiState.update { it.copy(peer = result.getOrNull()) } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelScreen.kt index 78105bfa3..5f6a13d4b 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelScreen.kt @@ -173,7 +173,7 @@ private fun InfoRow( private fun Preview() { AppThemeSurface { Content( - uiState = LnurlChannelUiState(peer = Peers.staging), + uiState = LnurlChannelUiState(peer = Peers.stag), ) } } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelViewModel.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelViewModel.kt index 21891070d..52401cc90 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/LnurlChannelViewModel.kt @@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.R -import to.bitkit.ext.parse +import to.bitkit.ext.of import to.bitkit.models.Toast import to.bitkit.repositories.LightningRepo import to.bitkit.ui.Routes @@ -38,7 +38,7 @@ class LnurlChannelViewModel @Inject constructor( viewModelScope.launch { lightningRepo.fetchLnurlChannelInfo(params.uri) .onSuccess { channelInfo -> - val peer = runCatching { PeerDetails.parse(channelInfo.uri) }.getOrElse { + val peer = runCatching { PeerDetails.of(channelInfo.uri) }.getOrElse { errorToast(it) return@onSuccess } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendCoinSelectionViewModel.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendCoinSelectionViewModel.kt index 33c03430c..0cc33ade3 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendCoinSelectionViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendCoinSelectionViewModel.kt @@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.lightningdevkit.ldknode.SpendableUtxo import to.bitkit.di.BgDispatcher -import to.bitkit.env.TransactionDefaults +import to.bitkit.env.Defaults import to.bitkit.ext.rawId import to.bitkit.repositories.ActivityRepo import to.bitkit.repositories.LightningRepo @@ -133,8 +133,8 @@ class SendCoinSelectionViewModel @Inject constructor( } private fun validateCoinSelection(totalSelectedSat: ULong, totalRequiredSat: ULong): Boolean { - return totalSelectedSat > TransactionDefaults.dustLimit && - totalRequiredSat > TransactionDefaults.dustLimit && + return totalSelectedSat > Defaults.dustLimit && + totalRequiredSat > Defaults.dustLimit && totalSelectedSat >= totalRequiredSat } diff --git a/app/src/main/java/to/bitkit/ui/settings/transactionSpeed/CustomFeeSettingsScreen.kt b/app/src/main/java/to/bitkit/ui/settings/transactionSpeed/CustomFeeSettingsScreen.kt index 01ea002d1..5e2799ff7 100644 --- a/app/src/main/java/to/bitkit/ui/settings/transactionSpeed/CustomFeeSettingsScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/transactionSpeed/CustomFeeSettingsScreen.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavController import to.bitkit.R -import to.bitkit.env.TransactionDefaults +import to.bitkit.env.Defaults import to.bitkit.models.BITCOIN_SYMBOL import to.bitkit.models.ConvertedAmount import to.bitkit.models.TransactionSpeed @@ -50,7 +50,7 @@ fun CustomFeeSettingsScreen( var input by remember { mutableStateOf((customFeeRate.value as? TransactionSpeed.Custom)?.satsPerVByte?.toString() ?: "") } - val totalFee = TransactionDefaults.recommendedBaseFee * (input.toUIntOrNull() ?: 0u) + val totalFee = Defaults.recommendedBaseFee * (input.toUIntOrNull() ?: 0u) LaunchedEffect(input) { val inputNum = input.toLongOrNull() ?: 0 diff --git a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt index 22d219d20..38a6c62dd 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt @@ -180,7 +180,7 @@ class BoostTransactionViewModel @Inject constructor( private suspend fun handleRbfBoost(activity: Activity.Onchain) { lightningRepo.bumpFeeByRbf( - satsPerVByte = _uiState.value.feeRate.toUInt(), + satsPerVByte = _uiState.value.feeRate, originalTxId = activity.v1.txId ).fold( onSuccess = { newTxId -> @@ -194,7 +194,7 @@ class BoostTransactionViewModel @Inject constructor( private suspend fun handleCpfpBoost(activity: Activity.Onchain) { lightningRepo.accelerateByCpfp( - satsPerVByte = _uiState.value.feeRate.toUInt(), + satsPerVByte = _uiState.value.feeRate, originalTxId = activity.v1.txId, destinationAddress = walletRepo.getOnchainAddress(), ).fold( diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index c249a4b9c..8d7911bf1 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -61,7 +61,7 @@ import to.bitkit.di.BgDispatcher import to.bitkit.domain.commands.NotifyPaymentReceived import to.bitkit.domain.commands.NotifyPaymentReceivedHandler import to.bitkit.env.Env -import to.bitkit.env.TransactionDefaults +import to.bitkit.env.Defaults import to.bitkit.ext.WatchResult import to.bitkit.ext.amountOnClose import to.bitkit.ext.getClipboardText @@ -820,7 +820,7 @@ class AppViewModel @Inject constructor( } } - SendMethod.ONCHAIN -> amount > TransactionDefaults.dustLimit.toULong() + SendMethod.ONCHAIN -> amount > Defaults.dustLimit.toULong() } } @@ -1584,7 +1584,7 @@ class AppViewModel @Inject constructor( .mapCatching { satsPerVByte -> lightningRepo.determineUtxosToSpend( sats = currentState.amount, - satsPerVByte = satsPerVByte.toUInt(), + satsPerVByte = satsPerVByte, ) } .onSuccess { utxos -> diff --git a/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt index 2ea8afa21..d8aced251 100644 --- a/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/LdkDebugViewModel.kt @@ -16,7 +16,7 @@ import kotlinx.coroutines.launch import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.data.backup.VssBackupClient import to.bitkit.di.BgDispatcher -import to.bitkit.ext.parse +import to.bitkit.ext.of import to.bitkit.models.Toast import to.bitkit.repositories.LightningRepo import to.bitkit.services.NetworkGraphInfo @@ -77,7 +77,7 @@ class LdkDebugViewModel @Inject constructor( viewModelScope.launch(bgDispatcher) { _uiState.update { it.copy(isLoading = true) } runCatching { - val peer = PeerDetails.parse(uri) + val peer = PeerDetails.of(uri) lightningRepo.connectPeer(peer) }.onSuccess { result -> result.onSuccess { diff --git a/app/src/test/java/to/bitkit/ext/PeerDetailsTest.kt b/app/src/test/java/to/bitkit/ext/PeerDetailsTest.kt index c2cc0aee7..960f951ae 100644 --- a/app/src/test/java/to/bitkit/ext/PeerDetailsTest.kt +++ b/app/src/test/java/to/bitkit/ext/PeerDetailsTest.kt @@ -53,7 +53,7 @@ class PeerDetailsTest : BaseUnitTest() { fun `parse correctly parses full connection string`() { val uri = "028a8910b0048630d4eb17af25668cdd7ea6f2d8ae20956e7a06e2ae46ebcb69fc@34.65.86.104:9400" - val peer = PeerDetails.parse(uri) + val peer = PeerDetails.of(uri) assertEquals("028a8910b0048630d4eb17af25668cdd7ea6f2d8ae20956e7a06e2ae46ebcb69fc", peer.nodeId) assertEquals("34.65.86.104:9400", peer.address) @@ -66,7 +66,7 @@ class PeerDetailsTest : BaseUnitTest() { val invalidUri = "node123example.com:9735" val exception = assertFailsWith { - PeerDetails.parse(invalidUri) + PeerDetails.of(invalidUri) } assertTrue(exception.message!!.contains("Invalid uri format")) @@ -77,7 +77,7 @@ class PeerDetailsTest : BaseUnitTest() { val invalidUri = "node123@example.com" val exception = assertFailsWith { - PeerDetails.parse(invalidUri) + PeerDetails.of(invalidUri) } assertTrue(exception.message!!.contains("Invalid uri format")) @@ -85,7 +85,7 @@ class PeerDetailsTest : BaseUnitTest() { @Test fun `from creates PeerDetails with correct values`() { - val peer = PeerDetails.from( + val peer = PeerDetails.of( nodeId = "node123", host = "example.com", port = "9735", diff --git a/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt b/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt index fba21ae9c..a113f3e17 100644 --- a/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt +++ b/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt @@ -32,7 +32,7 @@ import to.bitkit.data.SettingsData import to.bitkit.data.SettingsStore import to.bitkit.data.keychain.Keychain import to.bitkit.ext.createChannelDetails -import to.bitkit.ext.from +import to.bitkit.ext.of import to.bitkit.models.BalanceState import to.bitkit.models.CoinSelectionPreference import to.bitkit.models.NodeLifecycleState @@ -206,7 +206,7 @@ class LightningRepoTest : BaseUnitTest() { @Test fun `openChannel should fail when node is not running`() = test { - val testPeer = PeerDetails.from("nodeId", "host", "9735") + val testPeer = PeerDetails.of("nodeId", "host", "9735") val result = sut.openChannel(testPeer, 100000uL) assertTrue(result.isFailure) } @@ -214,7 +214,7 @@ class LightningRepoTest : BaseUnitTest() { @Test fun `openChannel should succeed when node is running`() = test { startNodeForTesting() - val peer = PeerDetails.from("nodeId", "host", "9735") + val peer = PeerDetails.of("nodeId", "host", "9735") val userChannelId = "testChannelId" val channelAmountSats = 100_000uL whenever(lightningService.openChannel(peer, channelAmountSats, null, null)) @@ -350,7 +350,7 @@ class LightningRepoTest : BaseUnitTest() { @Test fun `disconnectPeer should fail when node is not running`() = test { - val testPeer = PeerDetails.from("nodeId", "host", "9735") + val testPeer = PeerDetails.of("nodeId", "host", "9735") val result = sut.disconnectPeer(testPeer) assertTrue(result.isFailure) } @@ -358,7 +358,7 @@ class LightningRepoTest : BaseUnitTest() { @Test fun `disconnectPeer should succeed when node is running`() = test { startNodeForTesting() - val testPeer = PeerDetails.from("nodeId", "host", "9735") + val testPeer = PeerDetails.of("nodeId", "host", "9735") whenever(lightningService.disconnectPeer(any())).thenReturn(Unit) val result = sut.disconnectPeer(testPeer) diff --git a/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt b/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt index 8f55f55a1..e3f96a8af 100644 --- a/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt +++ b/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt @@ -15,7 +15,7 @@ import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import to.bitkit.data.SettingsStore -import to.bitkit.ext.from +import to.bitkit.ext.of import to.bitkit.models.BalanceState import to.bitkit.repositories.BackupRepo import to.bitkit.repositories.BlocktankRepo @@ -93,7 +93,7 @@ class WalletViewModelTest : BaseUnitTest() { @Test fun `disconnectPeer should call lightningRepo disconnectPeer`() = test { - val testPeer = PeerDetails.from("nodeId", "host", "9735") + val testPeer = PeerDetails.of("nodeId", "host", "9735") val testError = Exception("Test error") whenever(lightningRepo.disconnectPeer(testPeer)).thenReturn(Result.failure(testError)) diff --git a/app/src/test/java/to/bitkit/utils/CryptoTest.kt b/app/src/test/java/to/bitkit/utils/CryptoTest.kt index eb38f327a..09c2c011f 100644 --- a/app/src/test/java/to/bitkit/utils/CryptoTest.kt +++ b/app/src/test/java/to/bitkit/utils/CryptoTest.kt @@ -2,7 +2,7 @@ package to.bitkit.utils import org.junit.Before import org.junit.Test -import to.bitkit.env.Env.DERIVATION_NAME +import to.bitkit.env.Env.derivationName import to.bitkit.ext.fromBase64 import to.bitkit.ext.fromHex import to.bitkit.ext.toBase64 @@ -28,13 +28,13 @@ class CryptoTest { val sharedSecret = sut.generateSharedSecret(privateKey, publicKey.toHex()) assertEquals(33, sharedSecret.size) - val sharedSecretHash = sut.generateSharedSecret(privateKey, publicKey.toHex(), DERIVATION_NAME) + val sharedSecretHash = sut.generateSharedSecret(privateKey, publicKey.toHex(), derivationName) assertEquals(32, sharedSecretHash.size) } @Test fun `it should decrypt payload it encrypted`() { - val derivationName = DERIVATION_NAME + val derivationName = derivationName // Step 1: Client generates a key pair val clientKeys = sut.generateKeyPair() From e042680c7509c0c6d782276ec5eb6ff947741319 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 21:39:19 +0100 Subject: [PATCH 02/19] chore: update README --- .github/img/detekt.png | Bin 0 -> 449071 bytes README.md | 17 +++++++++++++---- docs/transfer.md | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 .github/img/detekt.png diff --git a/.github/img/detekt.png b/.github/img/detekt.png new file mode 100644 index 0000000000000000000000000000000000000000..792abe76e3e952cc329e9185918ed146655691a2 GIT binary patch literal 449071 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

sBgQnm4%7=l}vnZ5dO_O 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�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�$Z(mpqrD{4wi!@ExA}q%ONd?u4@DK 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ƥfv*2C3?vGa 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 z zb8m1;kSsRadZky9VMG=|UTZq(NpYl-f^76KLi{TMOlZ&Gv@e$ENt1T+* zUTsw0v3vot`}ljAwjG8qhi5!;E)eD}A;Ec7V1f7JJ{9HXLNK*qSF9m3Te+vlY zti$4Er?HBVhtI>Zb#3H82q`omJ4gv%;VEJm@aX{^e)xW4viKKypC2ZFKjh)caNw|6 z=;ZIB<~=l|kBNa{T3un-OIvHZ%JImpLh|tYx7AP{H^~Sx(Uo}P6j|(I^-0ZTBo=j0 z+V6hRP0$@l8RUL8S6!Ck1wJ~m){*$q*BVe{5}MVGy*QX!4wJIB<~qNwUN8VoMkM}K zLV#F2E>G?}Akap6d3oCviH{AC)(=5bml;BD0Q}4VvPJx|aj>aLXkdSAHpCo~7Q+L= ztj(Tkjpm<{_z9bKUIKlu$O}}wSD(@%Iq*j!MZL6h=oTygyq*5S+kd+DyVHh-RXTD`fYixVZDW#ojrjQm&^sD*M;^ z6DgbNA5;(0pT}wk8Hs$|-n-91uAnr=6;)=M;(pL_iTO76(^qc+fW0(o}Vsd9IscnL?bxBOHg`Q|ykG*{RrcNDQL&5&oAA4Vz@> zkaHc>QJtL`*KF!L_1kizRCgOgQ}Lh>1;ElRZr!>x7_dxj4U z4LzOI0O~&#^=hc+>s=UXU+pD>m(}F~#c#JI3k{dy`T!wh4`|%jHXGD_l3& zpRrOzeOsVeTMpRzMIn}RZ=ta8@H6yyOG|p5>$@n?ldz}Y)UVVk=kG?4q<^vX*`O!7 zTN%Ls?Tg)H^0Ekv?Wz~Y7w@+kixs_6wvTPyLosVummp=?I1T5yV!RO?J4J&Us9Ufm{lv@V2YHiH!RqpBM(7e%h52 zxPuN{a7SyssYz|jIRC+)5WWSYM;)4b!Ns-Y1wg~Kaf>oH=1;S8+u`>ScaZ?yVZp&Z z;BIuuS7~ab*J+e?+@EK#n5m3#e?pv7q*FaWr)xa*Woe}T8)`-ioh*7NJpT1t7K(<` znZguix05Xk)*sHaeI0#j#855NF;lnEkUbG?D0uMLZpHa>hcJQDJVNN4AnUD3no_#( z2VT3WDzjYalq-J}d=BAP(a-LL&7vi-bex*IqR)G zT8r*ZIn~$p6uqm-n6{eO;T~pUC{5hH`nf!vqJP727ZdPt+k%P!3bzmpgOxqjZ+&$i zm>JX*;*h^~cyv_|F1WaHe+~hI)m>aYXIY`TY3raao5D*&r+h^T@cA)p%=Cj2tHv|c zxGy}eKl0oSVX{F<6roCQ4JWm10zDu*tOzkmG*`yb@#-Jd`}r{-+pt%eBds@otoHh9 zH0;g+49HLZv_OA9RsHL=EH{AmMy?t9YM!L2SyUSI-st3{OB;P+VQ4Y*6@8#?-_6p` zokhuVl;kmPr6_$c$WDdWMUyL=9H|Mm1dOOpx$6wougczj1594>1A0i09>oDyNRScb zNQO5BUZrimx#0c#@qGF}ErVTLitd!;Q{FYC5OCRkHtg!@?g|i>R91nfl*$I0te>PvYC*ldr`nC)bql)a%H zOKtiFu?a^xwVjh!PGN%}esPISqww)!bj^YDmKwS`9s`I74s-F<4TynvV3Z9q>OLy&~_2o&7GJ{4}xZ8dN>h>fwy#&M~W3)d+mnd4r!4891DB60dlqYjs~nfHB*A;t5{z{l%$ay%D* zuw^!q)=~v=-J4}v!JbsGZfR-ZaEl_+EPML_#pA%UwoHcZ@~crl9&{Z7-48D;ZJe?E z@3}1iIePzKLq3wDI7jF?uIGSB9EFxlok2=3; z&HUa3?9NnJ1JC6S`hewJxw#DJYVk#|fHG=*ZGXyHOY8b$!!+Om5N5o5;Ei*2o;x=Q z2o+W6S`4mZ?3np>V~FeH;6<@thER3lN0D zH$C5}klVc!W>wm>bxD?PRxvl6tw9?3qDSubldghb4*1!e*^5=0y!(G-#Z(x1Q1r$! zRCJ!4e0!2oeWnzr2F#95sprmrv>Si=N4PeeDmO#Jd@Tyg{=4yl?ld=eXyLfw5KRAw z5jL%IG_dQ_Up+2QyT=~gJP`rWQ;%}z!;GgV4qIbY@jmwFU(T-SALIz}B&_BEKZm1Q z`O^m!ilRVRc}Jq@_9hY4?}+eJDvB=`Y`Tr(DIUqUniauuR%)g!+xELN{qVy|rP^)q z8$ThE8=hc?Hjj&+5+vt};?%gEh>xrQiY#t)b5G zde{K`2?!9)_U}UA?dCjGyy}!vnpWp3hkKct-d50To&tCs$*iwEB2!xK*#9n3UUDJM zX?|L&RW>OcY$`JxcOFc&f_m;Rzd2(Bxp9V?(kp@XAep>Mx>wWcV4Mz{>I)G6me(Ib z`WyVg*aVL0akoUzeP6(;&knInWa9Ou_kQ5Q^_WF%Ym@ux#0OpNiK~Vt^sg;NWb&Tu zg}9#|P0s;PAvKW1bsf5InL1>l^-3xZeYD)B4ZdlP{T>Z1Z4V>vTB$dD*Un58T}Qe| z0GjI-@NVx-%l32}4lP66T72N5Sb}#G!(Fx?NK$v@8}`O>q;)yLtZ}%$I!9i$NQRle%l$-$2)g45|8rxLva%@ybpaUXYyDSz_x%Gw>W){Gg zA4{)I-*k0U(PTMxX9ZP~-Wx@3+uEsgo5L`9^a9C5!%`%AwHjUTebTxGAi#*kB4tm+ z;Z2P<<-+xkHso6!AIOl-)dl$ z#J?+Ymi`n9Job@`i;GWBE;u{nE82JbQMV22Qv1Ri34uZo-Pz}6tN!-9-cG6<6vB&e zRQMYZ@LVYq7pFEty!g{p{#R%#h=&fGI;gX-Ip}rGO>3l6(-p?Ns6V_{K>*FL^K|!U zEm4v8}?lNRRhcD10H6gH5aStUFh_tDa8fV*e(ZQ48ekF)HPKvB*>_t=w>+bp)aJ?^_xf>N>ixaa1PJG9@;ezvCUJ3VyG=^icc z-+9vs-f7zd0n)S=r7z=}fgvI`JX+zb2hx}eEwHI$F#zRgK?E~_m6xd68sDvF%S<=w zl-jjbghFh0t56L=s4EVI4bOcaokk(+WAgWw2M8W=ory9^J$hck48<7pg$FmOC?9pMS&2S}iTD+uND0I66_$c?E<;L@R{(bjvltI_foI zvaKGqKyAh2bB#8ME!Zxp)25AItm=s=oLW5xAypFneoXTQ*SQu<=0@us^6*gDfzQo@ z1XOieAoRRCmhT7m{2eg^x0o1BdU_`X8QF-oCB$5<8002SXE`5!w+&D;Qg~nh1VlI4 zzLiZGq?_sUFZ{6bWj9jmtJLIn+WZctg3G(-=9=DO10d+WBMt&klWcZhIK$Nv)<+S6*X2`X76CJY8jd2s7|fz zhYjChkgL^mIQ05_(QCicjJF>?U6k0o`hOyY7$X6v;czGazo#2?Q1i` z^Kwcfu71TsZk>UoT61EHB7K8sKz|YT_G)0Xx!?2p0;-!ivF7xB(8#nK&g&-LNP?|K zEUpdZxm43GYj1t_>PY=Ls`hB1LqGeW`q~@TS92p3bt*cj?;5vD?vFsUc)IoZ>s(K^ zfN(;dey%Je^=2-5tX#Jxm18K+bkxWwzh=aAo+p1&%IiP7KTBSEzo$FQsG)*=i>3P2 zKHpffc;4gU!s7G?>tKT6^nBwA%X3ej&I;SP3kQfH&|=F1CjjjRTBV{pM)Si0sZc`W zsw&{Np)#p?fNsSW0n&I2CzO(gU=BgN3MYy!?uG5^ zdi3#K>29&%vcIbYDPENUPXNxmi{IC|g%LGs^|33(?l;~F;V@{wE9a~ySax2iwS&l3 za9o{2OC9TMV`z_d>;~Pc#?J;5ts2O&s2i8w5aZxbMNu^}0-pq=QEBrww&(a=7aCaZ z5532|N}uDp4!lA-=E+fvv$XBCX!w4TZBZ3=I?l{uJ4|oG)cCW$?Bkaf-rX5drZ((2 zz;Ze%7!8i&KP_^ESZoLwD`g9rKAnf}qwPWs_r&ukjm9sMKD;cItNsoa9+#23}Fw?;JePCL#Q zi}oOc!!e#y3(cstu(aFnaM@zQ4+w%v+*ifSc9B_cYXHSQpIK}W4TEa~9(sqx|1YObt?%<4j`H9D)TN?R;CXET8TyZ|HrnZTr~plZ3iclf^1*z* zbryi|Y69q_slBMtPOEJazlk~tg9kVSR1{RrvzSxKl4F?Rg{p!#qnF2Qtg5hyb66o($p_cJ1;2w5ZRw zA1ZUZS4=A)SX&#`gLVDt)avN8>dt#INBcr`T~^NhS=l%B3IXS!NsK;gPO3lRl?11o zOy=s=t@TJXTF2>>?Saz&4_@0MYZ(4ZbJ0`Q?gf%nw@AM8IHD z2i1^O!AVgRkx+8-j{U$lDq0FXjrx?lx9-ACt+srLv>ZgY#;cy)|yQ9+LU zX%dgRBqSh@=6y<~lw}h2a2&5+b;=1^1KM*joz67Wz9gO_n0Y(QG|Hn+(!@Z>Pn^9# zeS4et`0;^|*Uejf%~V&m@IlEYak{cs++kYRgl^ZSOIe4;uGJR>74jS(sl8_@$xi(k z)mnThsJLuAwa}zTG55ICOD-Ir&H7+-^YK2dW9719)U^TI<2a3TZa#h!fHTp}wNXi8 z=fw*Yrkttu3tky(##osdt%wv$+Z+P%jbV{+SOQ!k4~$breS4PVsb5LEgyl-u zES~E$(N~iK`9o7#|D3n}9+Ezjdc#-Q?mu)o4(;U1Xs-+J*8bw9b)`q41ahg@TWIC= ziMayipj*e4+gCr`q5gH?`7_@&umw5>wWaA;6+$*xw3u^ux#8m~-A_*+U6T!xsqZr* z8gf*AR8U|p+W;me&wX}$sa*8RY?p2is;SllOG9x5r6p>O@Y2{~Z#k0}SkV4@q3CV4=UC-E9dTzKKf9 zBW@ZQ@1O{Uy;i;w`+=Eenl1Mjkbpr-ChJzcp~%dw2qLJ2G&pj(G6S%YV94rcADQ0G z95ZTq;TShub`MIxh5y>TWHXkk-nQNsnfd4-lbY8=9S|x=s_cc$dbkG z>>x4^1dB{-1zM@cWPm9<)=8lV6+mEcv*2~r(py50+oM)J#U-FGD=E&vDoy+7;RhXVk1HyNl&4sS>Zmhs*r z+l!@HsL|L?>$xUd+l-gxUgqrJcss+E+rr0{+@C!jIgbnvyph)5{KFBsKLu`d z%mAf3U8y|bO!XPKCSO0r6+JK|lIoM~92kkBKF5n`@}xM+dI20yFjB8Fcc^J=qSz32%|P~=ge~w z+|3>SI!RZp1*Pgqv78fRYL~B?3;r@xY>bTBXq)9)pPQ`n?5wsKHR0S^8cE)pw|IS- zI?hEWvkdIGKp-1Z9<+o%b-ohi_OnwPw z3v%2ae#&%uOP}{E=O@P|z9x8_k`Q^K@c4cek4eSn<@;s$a@OOqYvXB=xny3gB!wReN?txuxSg<$KhgJ>2aenw zQor-f)z$N=R3QL06QnzLs#C;fw;Xg~C-|`z9zJC+OIzlRdr4ao{0G>BX>8EZ`)*Tl z+M%9+=QPYo*U&ZXb(;l)GF+u~8?)t@Pdz%O<%xp@T3i(eomizPgUqx9U-O(ZKFZCBQzvKo7^Nox8?r*6bsJNv)PubM=xRx&Eqf>v z#~OuR6tww6cj8U`pJgv7J4L5`=DIGK9-Li~ogPObT7seIrq_nyd)uqLU@BwT_*L%v zZ*J)I)Q-E&#(+G&13;j^dSNkG%ohrw+9a!R)*C%Vw31+p^N_8vBwXsxvuum>`{EV{=Ert72lz=7 z9e#UF%sonX7%wlV+rs5ZR58lamtNfqS{W1IvWwCyrazdTtdS=vu|UVkzev}*1;C)F zTs2+464|4D1<%!qIgcqY?0hVs*JgpQ2EL-C6@vsgj#WeFnYmJ_&Hh^?y4!-F{UKT8 z{uW8&K_|X+KJENlXKdgF*8UDFo>zbo3xEjqkp0~Q>aTB!t2JgyEmim57~E5i@>eWr z-m`nF^ZpezkE@yU%L_-mU-OUOy$Gt6YsaxHIWaM;nR2X{k+`X_$aS-CUV2NaZkPWu zdX)GBK&52gujf)e?eWkERA=NP_|GlD#dnUL{wDoh0O)z7<*A0bWw;W8Lo)MffHubD zaMZQoiT*#h-%Uw&gBmIzQJ*oi>A~=eRErou`=!I!Sy<#;;lWv6Q-R%X6QJ1uApz-! zv8>lKeKEG47!OagWEnp~M$MPiX{WJ5J^Q-t3Hv-S+FU0~?)beHNMfB^OAP4esEN28 zN_Z@*cPABtp$S3jOWS}y@PbM{@utZ{k*Sxk>f8D{+2xVqtyAe!&5mjNpzA2wf5UB_ z2Ru-{($>P8HmM@KI3yw&baWhRFj(Q4*vnpzDP_&WE2`k z3BOUU5jm#T4Ok{CMS+7F&jHuDjA%bn@=~Njm4WA$VO*8%gB&MJJ$iM=f6#hOcv=M+ z1T8fcs9(V}w1Xby-8Cxue!X!D>P1&aV4Yre+`@MsVAgS3p#PW;NH~B!ddEu)bSL}P zozRYWNUlpmT$0ZLsf3lkSy;JE+k4msBmQ_gc;Ai9 zH{`l(}9>T{4@Ee;!y=T-rBe`SdFTG*h>e!pq7jXk}n{}X>{ zJj3qScEsG<0z|p|{fTV`w_abf$vl8&dybm5W!p1|Rv8vlSatpi(oGjHONQeV7r5>U zzENxpjY$8B`JgGtjma)T+Pd7}9 zNwkcxXTrBTI`3R$Vsc8JK$&O10QJmvUmq$DVl^GyFc&ZGrr3Vl`+G2n#zB(r(8;V^ zfB9-%CVE>k=&)s1a%ODLV1C}o5}g_$_k)Xse*pUUfXxqa(6=@@)FjUq-mwLJ7{R?* zmBwdp^-D7`qggkpb?Wbf1lE_XqD${4gR&bz{Y%9gO5ns z#t#S51UcJjZGho5MZMhu@{=13Vh&{l)k?0p&iM9fQk~>)Rly#4jaZ?N0O(O_9pyNW zx>;YwvWJFO;KAG#x9IHIl~kb$@6K;m+uwqw!IRVP3>!=jjmmHKX(%`6*pW@? z_m}*;R(+QEw=cNIRHKPWJ43tGF8GET4+lbX3*_%q&py%Pm?8*Sus9x6lz1EeDsq9w2sZ_rMRz4Nu)L z5LTTB4D_}F$g3)@hqYzGf~n6xYE~mIaUZ^l-QrZzf_KO>`&d<(oN@$tC91`Yxg}?z z!u`XCISmf3SV!ZUF3_mmul56Y&I-!QezYV}o*ci8&cE~J)djlqBr(FaUwT*WX|`=b zJNFESchUxAk7qv`WD34M-k)zBortfi)><_Z{bV3Wvn(qJDq8>lxIboX-2y-#TpbwWEW(+2XlJiVR@yr+rG-r4NC;E?#{tM6zQFB;E1%4@r zU^+;-U;IFm$)0eZt5C>!JVW=l@*O04>kQmZg7wZK@v0K=Yn`46P<#0@c^ez z%flQdq&eAf2kdQbG1y*Yjyg_$LJcr=tTyH~*AEETF9oL^Q7LkFgs6Lu=KcIASJ9Z1 zwh}g937GicT{wlM&cEE6e~p!`O5nux=KkYHxqcxeWyQBI;Up?yp8KMp;O1+K?QX(H znO&0>q*x>MONpAs}6|L4}zVc*%9T9!92e)-}BiM}Q*tdRekX2~GLNTjr)+q?u@b}x!?m(%pqMP4ICyZfa! zvNQnjr!SQezVnwdUFT|2!xjH@*(?XAS0?M0<31<@LEOai|8P`v0*3y*_1l8~cJMALPb(UvEa?04 zxKJ{jw@P5b-*EdYajU8}nIUS>Diu`ie=NP9U$L2(e|e>+#yl$+HEqRpiqE)>FK1pu zDf#|j-mrU}a6zP7g#N#M_MaQnHhNc}O|7%sGMy*nl2%!)r<*h9G=W2Lc|GmAET8W)dKpq?FT zkwvuynE&}&|M8lb$01egEzV3*W%!#y#Ep6GrEhw-(O3BXUy8_nKhypqRQ_oZwnBpC zSozQX@1(pxU)xGjM<3pQ^H0~B|NdtDAQm;=9{U?pkw0H3iJ7^p`}*vkfBx6Yk+dco zDJr~I%fo`tdw+j@9uUN}Quo`IL16n<0SDxGT|h{?0XW})=ln|5+q;%g%KL8fflV_b zfX*uVc$*N7fT`}fH7vpoB+&WVh@>fg&XHaH!uy7BQF{(~_E0NqbJO|;QWiaGAo+Pi z4)lxiwng5v0}6bFO*eM@&O}$AEc{X>BKn7T z@1jrv`|NiM!vn%8@qnfK{`LJ-e}88}g!#c9gSRNXm6fL!EHro<7jbp>MFfN7d<7-L z)+$=tskyG`BK4VwkjL%Uyt-&){rN4;m}qCNUiv|6`}j9TyTkVfc9itPBy~YYtiqk> z=Uv;5=x<^JY*kCZW1+71q2=0SopjEmw0SU(*9e-0_X@5P@5o}3XNSl=j~O6|VQ-)ogCuM7mh^$s7Dn|ukefW({-9DGbX=&-R@ z&P{MXmm-me3kW2WAI^U$l`%)!2zE*xO;#q~3)kgToGx!?78^J0>cqDkaO9{&tE-Mu z)Hs4laDjLOByl9amhncPN}mO@w#J}Ss=!!euCpLB2>|~R@-vrj+-=?T>oN`VlmcmU zuWpZRt)F}>;!F}s#?U)X;#|a(|I5#LXW+W$zF$E**OLla z60^O*9;!a!pbEKskXk`&?f##))6Y$QXZj37Sqao=bCSihG z=WH(qO`)AuVPvgSS-=SI*@Lh{PHc?~WHz~01AaNw6~(!TedL`>^*bE*2l zeIQZs{X+kOia(wzDDk%|1sqbO4b;U@&@J?^&zzN-4HcneG?gy+g}Xy_IS^EkX-e}L z!c--ll~e84XSc~C;bP9$V{yM)e+{Laz&La16;}18ySG}s>(?m_4B#>=X?$l~^FS2L z70J;C&MbL>2UM;=c)m-->t&k9U!@MXxis|FK6wDlH_?BWsw!*`vOJ%r`5aus2#*H< zK2*NFXG@N{*Wh_A?FVe8EfSFEoDiuySTG5#)Fh5;->Q~pM<{SyjPW$}g?s$eq2GD? zL_oajWIENsXfAjxu^QdpD`;n7VbN@o3wR+qCH|E0b#rC!Od3YGe_>a)l)cm!2i)n2 zrPP8b4vF?_lAdGc*Lxij`gQ8mt?DMp5PPCm#}zf?NY zEC~d-S4^Hcf|h6b6hf}jAPr%EK(`0bGRvtnNA&w-nnOY}_VqVE z>gJ5$q8FWKat%Y%vjniB%|u^(pHpm(84$8=iqB>27vd1}9sty-EUz@Vg8*l}!LmB@Ym} zK$y7<{Kvzk*BY;U`t+%>54ZNNC1=PL$SDGYoa@o~1*?o43!33nXV|N6Te4Nl9{iWX zP?Z}TY2u~ayhy3j~<_}oA`;4gAO2bVnt^CQ<$;rtVG3EQUrFYr!TG|L`!dFGWX zI>7U3T|08P3(89!jj=qN;z-jee>6bHBeVawaFl!lkor^4 zaMz$)PnnFUk=iMa^KhWq+NG}QKe5T$tK+V367W8wbi3~H*U*)zCWy?@iqP)npmtT4 zt}t!iY7N!`CuGwTo^9x^p3LVM_N*$FY8_Ar&XCThg6K*YjK^r2hD4J_j21P+xo<=E zWvvbPW?CS1_m#fw{zhDzPWy6J87-&PTC$sF*{ButYUwBmwQ>-mx5|b*gAGi_0G219 z;!Y6+nKstBfq8Mz z^nkcME?Q5KOtrb-r%Wzg(!6A695mYz1o1F&EeoeUb@7I64FC@>+b0vSeku>z%B?0y zK)X*kgCe=5@QwoZw6C^^G170Isjk}(A7oB0X48|xN5Ah9+4(U6(}?gG=kdzAcL!_P zCw^fsFc60!I8^5^4i=2>+MB;LeVzoG$qe5K>nQ@BZxwKiY5^HSILkWd_oi)Jt>ViI z0?!}|A`8c&Mu+F2f~AIWn%$sS(m2*1=!2!Wb+|J_Q{6{EljPJ->%8FQT_@p#eg$-+ zrgQ)o*#LaV?pZG9@%naVzx#Vw4=~J{e{BDqmFNdGNE2D4u#hn}@PPfsnV5p;d_##my=}Af(o;ctcq+Wu-};W8Y5XN zd2*z52Lv>Dt_r6%OvM1<`WQ>6;XI))_hqTyo<6{ssZy-@wwkiKFG?s?4)mr9so21= zdjFxe`=i*db*0G8AumZ^{;D2lIPFTou&Cf2uuwv?ju)jV+q&M=LUO=3&`X;us(&eS z%ZsT5Av7LAMka`sqonrq*?Rv{aC=T*9gut{4&kqr!uf`C4}b}mB>{<$brx(_oNzo4 z{q{8$Rp)kv;YJpb{(cV4$d(lSbWZox$g47wRNMQeXFeQxmJEo zY4hIAzQe<_b{sdU?-coXXu|rlLa-}3^$B_o-G-Vz8@zS%@QKXV!(f zVio3q&u)`G&ee9q6I3;e#{+1TGNRY3)K>g>1n^K?ZX~@((kqTu#qcSWUb!R@`v+-} zxN#^#XcRTd1SxUet9-*Azbosd)*~`hKTq$ou6B?ban=Y`K71cn+KrVy{2adx9VY~A zZ%g94hUc3lzwC++Ald;T%udifG42F&Emqti2zOhOfH?{#9E3~Y7~>k&m{pAqOA|nQLAWckTW%#49*?4SLSot zP1Q_}aNj#vctV0ms^m;7g}HwBIsNy@9rEOqqKW}q)sJA} zEF=@FUZZTsdcwka%d6Bj16gU}91VRLUXvV-&UUOq&_FA+h!g5F1)WFr@ngUsRP4Ci zzo=C>h%aT#M^CIDXapxTOgb`E*#nsc4N0cCIM7ry+5gSg=j$#`V>{>5wm*q*3#AkA z!uoUcbJqBnAGI7c@%NTG+qC3s6Z=iWsOUh;7K3?6(ujn)3LjIiJm;}I@r6RpJ*g%l zB-1R}1?3>$tQ7X@)FmD^c;0+IgE4v+@G=Id&e)FhN#`C~+|h~| z0C|Q|CFLUW2Oud4ckd~+hC;Cau=K@YnL{e4!$1{wh3}YNxVHeLC7?gPYW6kd5wLb zXO_p_RstYP=xQXR_(xMjGx9R;L));8O+vo&Kq~~KbBJA1Lro^YcbrgQir_oSmye>? zQ2TGicnG%&Adc$yH8p0JC{|vTKKcmpe9IkhHE7ht3%w!%s+=T}jbb#Y9E%xWW+s>OXtpJBI zS8R-*v|$J-VXMfIx?ZOdqchW{sYtFwG66!Hgyk*`72DT%?1FBh4_fG5-*VYWVR|vA z(2PNlr#OW^XiPRmwVA<#uX>5T7Q?1LVqO75G&Mr`Y}8z-h9hnox%=Fvrg!bCqA5^6 z8!w_F^n*uOp8T*YnPaTINfA!V_1{92*yfLvOnQmIKe-)jExb6{3P^4CvH7kbxo zlqz?CN!=O2RF*d+NSMTHr-ly%BX$yeIqrVyLfKrxOgK%l#(wrdd|F!}VY_aDqD*NVO90Y&*GYuy)Z5bYQ}U)=cvKnpJujll(edtrlQc|7ju8Y zQ2+U@(&?DDO}2=23Htk{SH4Lk>dRGLfn8?pwaGP%%w&}9+rRGbl{yteRl2~ui4~Ct z3+G*Vh=P&mJ3yL8)!?6!DC=mJjM~~-vSnLP3VVQLpKu;xyZ+y#{3? zg4Tbitnnc|H|BSP?jC)8u9nGi94TMTk{0&<)fKd!{8bcaiY=*P1JE zjR*9PUu%X*0e+cqt48HJ+kQPARQ|6xm$Psz=+D}aK9xTbD_yzt_#F! z?v|tNw1WM#z_XYJFR@gowFG|7Ku1BFxf4#euk=HI6&00b?SXPsCVCA9M=h5&jL4+X zzxjp%L2h=Vj(bt)K^$(piG#Yv|HChe#J#0u z=h@_=Lp!0zFhg-ixPVGV`hz&X1qZUD&AK7MK<8$|+J|2O%YcKtv~D8stZb^evg6)3 z%u~S8Op9mVFI!%TzQir#z%(}%1 zj{~=3VY&ry^JFH`GG&OgN#O3K3Y3)?sx?q=1`ns9=W4>9~+-3Ey_e>ogdu_h2x7wDKj{G**veW~fk)+q!LYQ6?<6 zv2=CC{%zq2Chz_v^+B25+Cd<4Y1k&N5o;!0h>jx)5EBo<5VoQtQ)?kzaUAoCN%2-5 z!Vy0OeQ9F}pp|&csC`jT*-6`hGpZAC5oagt`zM%OwWD(Ml&pWiNM8yjkc_Cl9+9}| z<2jOzKXN!~Z(1Jr41ILxPN;N1h?DJ0c{9!K0HC!dW*dG;e}M9PA%=()?d{7u9^4F< z30s@@_k>eJD#>>3CV~pM&gZ8#UtkcqDXb_&xoh`c(>$&koR$+_c;rY%zg*O!h9YLh&!X7<(w3>2F(rbc%+HpxZS>j@pqkN(w_;$b){=Gf!1kKO{vlQSU z@Tpw$Fh7g`QO|6xUg{&(D||mapU$j8^Fcm?CX9``*40#6>-L8vNg^s?!S`?%cS_SR zec3i9c~I2351BQ)(tv%x84vcrzQ(OJOC?8|2ER94!@`p`cThUez1^i{Dc$-dAOa9I zeAnie8J0a?x6yY!lZCZcG>^T)sn(+G45NFoux-Dbas(s07{)t{TF}lZG}v=(^4^ep zVDw^u-J(zc>?Lo&Wn!v+?yeNS*xdJYxt!a&ecHypzV+BTb=NF5q=6a&O4xg~(Nl}$ zwj;(z%O*)}1Wkk%>cux-F|{IpRHcZJ>`;wP-ej^H?xI;3)G-UGmXndBHXmZ)rj~Mp z(n*eqxHpP6sRTJ{pG44cN~W~_JR(7jC$z?tB+$pyCRJjHtX@>?qD%e?L{ zk8JOhw_oGjL%lPlXL-}&*IdC?hqC~rk^k`E{_%^OB>SvHT;l==2b0i?Mi%S zr|}%12XBiE4eF!J$&eI8G2zNCeqD}kQ0lRgd~N1=jnsjQr$Z7eZ^31z^Vf}JN^*NM z=5EOF$uh*3)};qin9*hXM|$lEv&eVz!jckowZ!#|QjZnqMAuNZy$te6&}>Zly$JC;E1U>jX0Yl*%W%IsTel&w{HnOgLN zsY_dd!t*H6qHtQ(Z?y^LzKDW^SvohYy-Ow(ar(xWKA=}o63+Sp^U!=eLI>SU0NGVn zmVIe_4c2#1oQ=Kd1aE3SF9(NgYrBxed4@jd6^lTxeUXE{f#m9-YR3(+cXwN;G8cX5 zbLUHy){y!0_?_3=4V7FXg7PXxsDTEUns5-Ir8Pl{@%DE+@ztuqJo_4_d18KEm1s+i z1qURK>Zy!VAQbFPBRm)P@S*9(!;xDET}8#*lQ+0c%d#?aG;vw~WtPHYHo#PHXY+rR z=TGxovcq;|tX(rkIo;uwb)a%2<5$9(XWmLhh_Zf0NXr30a@;*6;!kN73q|dA7U&B=nu0N9Y%jDA4U_p2d##z8a zAn2RA&-nZEt-lIy80gY!%oQyX%$p9z%lxnLM>ezPKQzkke2^O=54r>N0$O%gDB5W&#}-Tq)`pb5z+!v`_eU04L83>?Y)fJ@&+L1vy(5-wEe}l zFo?8DTA%!XX>?Ajp8G}Of>Ws94U-UK=Y~NmUp3(m=NaZYf6VkS6Uh06?$dL3_I4*$ zuTG4gp=(dQAk}O{Sd-384AzvaRbmbHJ}SLS0sC-C(|!$OpdD4hYkYyJQu9guDoYF}jt#ecpVK#u$7T9`z&M6MGK1C(J3Bke4_-!| zP4K;WtN(qa#er|bC^)$Foe$?f<;mRBSX3-I#PkZpf^R zJF%4UBxnI#JBfJ2g;i*qI%D|Wba(l`I4J zY8l@kh9|`ij#O(J*M0vO?l3OdYmlqSE9tpnD;Vr9GJbb$%Ss7#aGq5~4ai@w)%cGK z5>1Dqt-IHSF1{C*zd+xSXsdn)Hi(=42H_JJEu0gV78M-{^vpaf%K(qH-d*3fx4#RT zrn0QbCV@|(8G8|h?Jqeqt)TrL9GskJ#{h(=V3hmSuml*TrZ}t1S18pl$E{Yr-;DJ2c1~%wwCzgsA4>~TRq+yt?00Lm@3Od=bMVHy%_DKYtP+y># z^!I56L5q)W9H$LJZKt!m?13GQZR(x(4YP59nd>fa-gn5uX*OQ=Hy?}=>#S4a(q%RF zw5od24+#SO`IcLZ()$0K^XRU`s_M=~$SzZ6z@n4uTAjVE?iL#ALYE2959#qW_40&lW)ba+nb3xRDLS2J8E$`6nEt0UnULes6g7F7M*pa;6P3lNVEe zjo*lDm5Ej(*KvPlX11u5qieae=_Vj=Jp0_<4l$#B;y$&DOLI_$=@gBGWMwIZU*6?e zwc>O=@Wy4-Xr5E$Hm+AAudBa??e$(s8XLPxTb6M2z5uCfVDM(B#02fH%sQ8p=De9O z@2aV1zOh;}C5Rl7uHJ`JU0z(iyy3r!u0hJ2?wbZp)(%?ji#-~-$UC~UzvPdb2(ym1 z0~mQyNBX$3@7juCrNhfx&`h~0$j`#$td(@0xH2Sd5l=|eH)V%EUD#VLO+L@cRFQmR zQQFq?-Fa5#YJ}ergufCAKXg)5R`yLgTr5DS>YzA~&BRK{&V*m3K1k^(O>QcIb&9jrUFI}qZSFv{SD7MHRt`r#KiPTtmaRL zmNK#hvl#`I7o2Rf`XgimOP_En$sUpIx10?JjoTI$%8PT$PcR8dss@@6C`MJNNI(J)M8EyemEP?C~8d?B6 zIe}vG@lF6%T}Ll%C{fd7y-#K+=m2+HD>Go*aNyV#uQYMDXA#~D$9D%Q#%z-=nmnhq zsv4z`Iso@s(7nSX8(_QL0`lAw>t`$Yn#6kVe5)EY4N#i8CI3KcBztTOo=F^8H%Cex zB%GY?LiXh17*{05$9I?e%ln{N=n2wDlHKV8f))BOLYm$n3)tXC`LJ!cAWZ1Tf8d5Fd1?1~Ns9cBYl*Hm~cJ z`_PV_JSLWR@0L;X0DJHZ2qbEeUL+@?8hCSc1Q0MmWiac#P1)HIW2b6-gBQMHM&ZsK zDS2fHLIPKO@1$7Tic0tCo&tHHPiste(e`vA0ZAD=%D#B|yF#v3f#)LK9%F98l#9S`Hh z)e%Am8SbGG!g5;Vm&^hem2elfO=KJVo?}_#HMwdwH{FTju>QzEn%unnF0pySQvEX3 zrQ4ihVg;?uE!Uc451Kr>c44A9w`g16ghV(u?>_5%^}aWAX-slsN6_skQzDNlrWHk_g&?zq0`UxkeL}v*3oXdmog2CmSeHIO(4=2kJ1yzUqxNnUVml7T{jxMOdsR zrno({=UWsA@QOmOKB0OUuEAVPcG?zJJQIy~QrBdM%eFbkQl7qiu|rg62=#s?$p$l! z1*bfHr31^c^F|n+)Ti!{VoPoh3OO#I6p>n}qGuWSkU$mw>Qxdi$Kyu>*-tZ3Mkl1} zQpo#m=M;Pf4N3ZoWT8);;52KDiO}{|dIcl7|&0Aod%@grMJyi&Y49*`pqmR)P zWecc|*SLiNZ;-sm~OSTIEXNk`_&Na16K3Y1=YF9{$tUNE5b@Sx+gL{cGj%$B8OD%*Il9j!W zPfLpzWpcCK`nMBNq*E6O2pUUoKi(S>|P7FC$z{Z?LK$k#fs}I9t%;p zG)-g$>td{Q|G$qEs2gDAeP6Tr4;T5z8x*Dl>+1Ai9VPR+CfmsuH<)IoyquRC*8-quA1~%n8PEY- zYg)C(a=o5!TyFG~l#rOejCuWAjePeKWkp5BY_eIts{8!}#rDst1_milo;*?2>XT7Z zQ;YR+!*!8jyKcdu=_Q|=E7H%O4wu|G(U;i~UM&zk31v&rAHj=l_3u<^P*K|72$^|4PWK>*oNn zkIVFG7IvC6SQ;tjhQVMYW5v`>1RgM^crRJTCOTXS07xD1%;Xv=JWAgv=s8+01v7tc zgppj2WjBgDJJ&HaSjMjV=_DU^#tJ!a#V77k)s>&Wv_rfjzX#8EkELDjG_HZ;`^4kQ zq1tk|TfhAMV-0!52YMGuM^6gB?}15}Y*$RZV~4`SxpQxswx=L2FMFg}d|VCiT@s%>q1d%Rc~LN2f<%A#>$B!} zJ?tetK$m{C*LnYkhl$6Qi0c7$7)c=Dsu|M_x;<>tye9O*4mZln%P&|QelJS(xuc*k zSFXa$l_g@^?}6Ir5wZqEaaY(8!bV|eu#F&!C8t*{&1(A{-F$;|*@_}) z)}h`Td#Ty>_uDAIf3)NELc;z2EJ^yGOYHVXV5T7PQFgk^+s}w^6>d*8!ICpOTfDxh ztKI3`a%K05lV-zQ0 zXyS;u^KP8X8Sqij6V@1DoENHcd!t);R&9W)*3>k)(GU^Sy})2?=4Q zEnt8Vs>DPR(7ZvqFC&{Arip5``o*Qfggupqb*fmn?@@msCLg zj}F#owd4{LYoLFqaKcEq1vo3hGeNG{0@#p^@GDyjE(`@Svo2U#H=q|HVB( z>4cJ0nP-~6)|1V6KxaFi&pn~lP5|b^9j*2y>x@A&y)|HzV*NUp2Fy7CCJIz{e!HKe zOzkHHaG#-X09=Wq6Uz7N<65TXwfE{1#{p^yIWn*6Glqmg7mH!bKA2~c6UF!%_D|I< zWQS{h*U!fF11}h>wMlV7rL?p?}gRf!5l|eNhS1%--I3lwD5bpH9$sr1> zK!Z+iZ>BUwOcub>bhj6b7*w;5^U}zCcSf8(Kn6AQ_ak5x)OmS%sqf@pZ|9xxFhgf< zN^hG4ZQ_I8PJ&6GnP(Jze0(^%?9(Z@+4t&Of@K=2Yd!mI;(*!vW1j-8{!&51l#4wx0O})*eR!F-z{Ib z(qf9GL`TOx8nk(aSEClb4!X?;&aW3?uaL8Af_YXbSr*&EZb?sgCwN098fE2DrKztw)WQd{=@0sO04SjgmRX!8{#k^xvJfN*VPH>Zd$O1pHjoU{x@sy+zlQ%<(!Wk zoA-|$?|rm6wond?_1tvriegDV_pZZw`rSa6=CD{!ns5S;c>R^c{QUebV6?>}T~CNv z%pV#%s#DKh^aS%ITCP$gNc=F4F`lmJ;A+l6~|*bMs{!>!^YZH@wJQ(953vGJ749FX9(+} z${L;Aprc`nrJZ7a(qV;MA~XQ#WMQCO(&-n+F@r zuVyp?vI0djT!vR>4_qA57R?OpcBibLjfgnI@No9*EmuTZg@!xmYOhdfNJA}UR~Ql*1RZ&DPHrqX+_Aw*O}ML>El(t9WLB1kWxLudgh zp?3&1`7ZX^`)tqq?4y4F-Z9?CF&t(XLhk#%+FEnXHRm-B491U||DY<>*h~)ei=FlZ zEKIb6f|(1S_1MEM5sVJ$Z-WZozD-*#zyV4>`s_}1SQx)UDNwVFn9L_&9KJ1a9co$3 zyu~++uapy1i#?F9!L4fd{B}n_2e5(|+tsztUAzcqSUTBD)=YGJE%qunp#OA_|KtB2 zX(rgxOHSS0zF|9jW-j{W6;RLpE$P(h+>mMiCBxI+z&=4;53(}wa%dQk>g@YE`A6%n ztpx+1LHG;TMDs-q7VNy9;h)07i~|~7jV^CO>Tg~vgA9we|bS^;oJiu)$7J&_GPOggRi3_y6Zxi=qJeNu3Ch96lK zF0%2>mJLR#T7d?qP*6;51GQh;b&nK*JM?Aq`qD0NhP5TZQv#LFYn!6#nTJ%9P8*Hk z!vefzW#1Tifjm5R>!qr%{~CIOxsO7t^YCFG1M3>&fO#K^1pTeEFoG<+YYQX)yfa z`|e$c2;@WffD)o7)uH=u)Z!ms-Mftc!Qb-U<<(D+bVodcW>F41JG;W?(*%^f_HR%- zYjQ}V(~r%g3QfG=!AgQi0?OIh+1BB^NwYq*jAZwKGGy+VU3mu+RE?$3iH9`8YL(`TBFrr|582(CQXU&aNG`Y1-ThM5>9#pPz6Aw6^BpFi_(-MWOa zCvpHr3}+P)sebe+@cMjjNi>G})SA%H04eB0RJnc07))a4TmoV$8GyxtzDt3)a?bft z4Jy8E8kw03=4Qg~yTWRz3X#i>NDOOU#Yl*kZ^3B0!jsfO%buS7Az3*&mMezIU!DV2 z0=whBUbTC>08VfSKVTsEcM=g(?#lwNLDQJpNj#MdN^O@ZXwi<4iIOYPe4WpBx<+jx z!6TEgv{Wp|p-5Uf`H92&`_&;wk8+)Umy1}%yMo+2zwXU`{ zo)j?>57Z%T>-QQC|1^hKYQ!Hk>fd6`Hpf$AL=*PDdHc4lAwZb%!P_x*5%-v9lspiG zAOAQTiQiRbDw&YrV1w6>#-x-cRX~U0?3}hW8GBAx#Bj^SNNy%vKy}n(8Tn*^V=DS2 zN(aFe#PD<+XSWscW{-mG2oT$%S^%IcGl_Eu+Oe}MNpWonMIwCrBo8G{t{6AmE?)vQ5{q)4l6jLtJhMa4%`*$^TS`Zbb{blrop2hWEFCo)_{(w&rl2XnMpDIuphy?(s_{HbRi6o3Qr zA$zmo%$qCxsFvC;ks*TI?eFTouU=jJ+6={wm!2q~kX_na8PcCEZ09I7$m2qKZto;9 z2kx#nB+Y>AtMO>cC6@Vh-$NeXZZ~v16R7fEA%2z#QYPm2!OzsC#fZi9+;)xKGyNr z2PHh*3_{GLeWTeW+(7YdCO^tu+j+Hv-$hiub9cM7nU>aZpCo{a8Jv4zaH~-*ePY17 z2@Ox-$+PR0ymOLO$GjvU>fD>gu(+Vc?);>Ccmj{`7GG6Ben8#xD_4b_i-m=zD3Qfx z!G(A0a5UiL!>bA(MQ8g7^X=(4=L9UJOucxaNdhFYCyI`Y8FJC6QK)KO< z8YsQvL99d)B3)0sgE@t9F-L%nbEe6C4OAL6z*#J`^w~?4$}q%YumqHM_c6zqwg55g zBvdYA4JQDB3vagEmX#YZwBlXQ02$9cnEe z0B;@EfGB|-2ZyIB6G^m?egmiS*34w1?P4+vRac4YFFA#J)!}DGK9@X0y7%f~8@W z+8`&_Ey5TAQQB|=|AiY{XdDBeI8FGRUxs0h>8T^Q?Y@O?e%))fD(COKaK%_IUol>E zoZ$G%z0Wbu#oJoISwLaG0$9rQ+ya`FtrB_Jz=6lHg!0pN4RENQ>_aDzlHE-Z&Q!n^27A$kKQ2~l;Iv;%LJZg5yU3rUf8Pi7{#Q=n z`T2(^2Oa(={{7Ei^+!ICaN*4THe2gd;0ULBX&5wX8-nsxZb*n~gdg({KK5NM;S~hx zG3s3WUH22l@N+AjAC>F+p8pAt^DoQ~i+?+IPWi3pFC}Y#+|&Pm7ulnea?$^O$M^H( zzYgsGKC54POn*GT|9w{fFFva`dqU!{0kSfOmOJP2e&^tsPdolAPKr>U1v=fLFb=r(Hwh+fVL3;DCYtiDNn_s zuZMu-Y1P=sNUpFP?!xM4;fiSeL&;Qp;e7uc29Xl8x<|6n+|sfLwD3>PMV1dIPk%Nz z{pC`6_7^FDopCwNkM~wflf3uKSqSXx>IwrIOznUM@|>H_?cy@(1ghyRLPx3=&3QTW z_VpP7W;n>93MLwkSH&<#zCaX}0&)Zl%7V~wv6GbAPlwhOS_pm;t^fIS9x0tX4pK*> zY6YVUeC}B9@R{@^|IJS(pg!}Q*IWj8o?89ZJ%880sE#Zg;=k0C6yOI3;(sRQ=9$0} z%Fr-*yF4KeRO1vUJhq6@`6$degedwPSJb_Yc038G6er?Z3iKZ%ARhS#NX`&-*xR1R z(&H9$5*Ger==ZMy6qmemHuIhD3q>;dIxshj&60R5BW{D$V)DxN1K{6X|XNoiRR4=AO;Hwk17w6c2gBW0h_sMx3i{Bzgk%c{ChO9Ve{q{|Ok zU%nDT>wxKzrfmWG*UJJ2HJ~>ZB-o=yjcsJcxip>>xS3#Oc>stkZ`jme<(kAqbL)nC z%cQ){A%E7+{^z=H(*h-0dxE@=;eE@JQH?T1lx9zofD}4ur@i{`qwz&1zBNZB{rx;A z>Qr9`vll1}ZNGT5c6OG0k$ZuP`JB6CsB+)*1p6nTlC%oNz`Ir^T;Q>PhUdIX zm6gh+#fT){0;zN}~(w)#W^a6@?Co z0`Sx&O&KHuT~}B7{yBGuNub8yTmHBl`=2xS41T7^LUI3iCDF@2Jt==Yx&M6E`()A# zzq$TvbL`~S)-T`aZaM!(_t!rGswD|3&q>{Xax{H+VEjuT@sjh850USGUqU|E(!3St ze{n{heDn`}MDgK&6u10)48MEzSCND8e;jAuU&(hLIMGKu%d?61oZ{C%K?FEw|2rW6 z^@0A!8~@i1$k~k%lV2S3du({0Ro-8ITwB?nKJc{uMYR0RJNLQA`k9aE0@|MMi?{73 zy1A7HRh#&_Sp|3KW*Mz@%?81Z-WsM@v7tk41^&?N4F3F+Kqjz8VL^KwQ zD<0Ncl(KIv*?E0nO*m!rIgognwNOtQai80nEp&xdEL_*3HoR&K8t2K^rk@a1Zm9Ac z_H!n-uq*D~cSLOBUz+%BS~qUx2J!jn>jbJ;!}oZYzFd{6C^KiCm}Abte*w#I_qT)kAJx7dC{rg z5Ej0_*w`o!Q1}yTrO9XP#S&SWcme_fL7|}xpnIkTK9ds^Sb)w~ed9gw327m4=fyI-c|S-A?wGVHyr`u{7;snNM$%O#-d! zCJ**zX8AeMzo9;-@1Q=|%JyGapIll7{f~z(p#vX?sx$gU^90`m#Qsqp{HimXo164V zeCiziQYptu;b_s|jU8$kDd+10IG_tngNL_Wo?DJ!jIB0r|ARo^)Ya zk6iB`9&ok~iA*m^FY&F=GcpcN=!24;<#>gp>aNMzo@~D2Or`{6HqYxvilk$twE8H+ zOPSUvAT@ZR+-Y>ZW9prdgl%A;3Y^shC5kLCs0686Au^07i#TWToGBk`X9YP84J#;$ z1x|jtba3?qo!7CT_d*i+O%% zz{}u;X4HU(cOk)FeGp3(m{=?HI8^5_#uHPCf#*S)iUPNCw?F zgXK7J;!ax|E@;3HWD6TlRSzS$7V0t=6*O@g9a{6!bNAo^xO2EspLzegOF+|T5;&bK z7P1+)f7~IZ8d3FhH^r>#7Fw@R$to*{LK!FDq5B9m$rgGMdhuQ&kX|cf@gve_ z$p~Z5*5*sH^78DY@1r`q!bds}UFVdrOO&#sd%oiVa>9yKv71#72gLO5oA=+1w8(@s z6{wWpZx;=j+(?|TyKKQlX_R8~DSO<)NdLgNwR41Bdvm>|3Ek>fnpvBhyW8$57LgKkMKGMVXW)&R7Tu)2v zBR_pfPlU?(z(fud=8HZf-tn;)q#=~F_=&F-%=UJ8^R$>wzjX?VmVcX5=$vP{wZ#1y z@m7>>WIM9QB#rH9?2~ZU)XuSL!CIZDg`OKpZ^xzOZFgi4c6^r}oq{rMBfCu=Mu!de znKYZNnzSuUS1$up^NBOuh_5JB^CO=bKd-m0t1EGa3Z2fY*RK^a8y`VBmzUYL0)}*u zmHZF5xOPWEd@|<5&K|vncZgnQ`~gwJi-qkG0{^3_8B3>5k?~F&3)`0*!dnRl8AnGZ zZ7Ie0*qx<8eEX;GoBO#=(aoJAV-F82HZypSp8A@36a19n!({fPR76)8yKIX4^vQ9h zSD9nd6*7Q|s^Tb5ob6q7@vPexI`dKZ!LazVT5;aPkJ-pw4Npqmt>v$@kTj80M2M)i zmYGL$X!G>_1Qoa2;q|=<^H5kzEdr7A@F@S#~(mjt?^77@&mTeFG zM32$&R`3b)>rPLOH+ueyVa&gBxGVBE_y&(8nuQ=$$jeMnT4 zdEcPXGSYyX!fZtW$Q>)5_Pc-ozGZ6C`n$8#5m$_`r#|Ca1~h=&7Ckd_Yrog{3+&xM zZK5ngq92_t35!H;-p*;n${-{4FJ~>v*`mFO=8F=66?75lyc+{0T3u3Beq1-GPauux zuQ$}9@OjNkS?`S3h-fc+s@Kb&IY3I(#lI9~1s-d{LS1D?CQIi{!ZBP|Zgi(#up@C= z9F8gh`Z30Q+<{%8ad8|#xB_^c!xVUqL~Hvj>H=%PlxqP7=88mLiBpT8zU$9b8ya-? z`}mP(i!XF<@1U?N`NddhVc(k0weMp2|A>eG6~5hmdIJ=1FSc}yX>W`B-^$mob9)j4 zmdtaW0xx)W_EGW~BRBRrQ7-%#lSVgZxvgCDuY9a`bXRLGRMJunQyw4QVlM{Q1<6mqpsz>3S-Z#9OglDv${pQWk z*86K$E>9K3D}mGRNQ4y|$G*0O6mtaCl#Ao}>L%%+{90^2u9T=Sc=H$!mH)gNfOTwu zbC}{x)A_6zqVeHtBa=*$l%JKj+C#&TY@M2~hWFbzN|x^Y{zG8m&x6lj+}8ACQL7MM z3QJwlFpq&~W2EvVtK){q@HfNKYL@taje# zq24;iYIv^KPY#MdzDnHey!!cztSiisB&S%xS9y})c}dNh=+1=l1gn4}HW|=1f&jPY z^vm64SM1`}xF*lNon$LQSmzjFP5+{8;d@v;OuyQ?T_ezQ5| zaQKUTRRA%ZbLH)f;tijuMg$oMI)(sYzN

}L>!kxlS1U3DQ09fMB}sF1WgoDW+>r{R7ENfZEML5iJfQ|{-xS3 zh`iHZoe;L0NOaqSdGAKPF18xZ*8?L&V#@12@qolXq)WGAc;mzm2dG)dKFNE^;5LV& z;!_BjFo|UVyJ+BaB`v2xvtKx1v3=_3=y=_gXVG24W7gZBYZZ9zQSXi0RKGG!!P*iZ zAivQ)f5#JRx3QCQGFfU&0>DzZwl2p}lU&QxG9R5+8#JU3%MmXx0VIW%05PQ?*4#4H z+^e=JJXRy>x!lMAK=<5#nfuuyLz`3S7Tv9fLuEz|s^aLoKWS$8cLFlmLUvZr-X`Y- zN{cr*G#yBRI|owpX9rhRRlOv?28_zXb$Sv0v0^w*x0MnNB791L;CT;PkM%eOP``(q;W|g#7oumtcPWl7xMPC~l-=NygMPJvl9{9Sr2Dyl)W~ zX@pNbh=(4uN}LX1R5}{#qM@Q;9I~PMzS(7 z*{}~10g9AyvkB{5zRTi| zl!`qSbXsL&e_DL$t|T9y4U+Br9D+aeE;gOs<&j`}6@W7@|9+iAKAb&NELD*;RyH!F z;|$N;`|9e&)m^!|%t67yYI8#uw($=5he7T$I>pQw_`urQIw6fK_rrNdGinwZZT0Y` zje$mCsX_-Ae+BIjhN3XTgHVB*YFUn6uKw$=*(LSb>4O;c2UPtT)&Wdbh%lSf)g7U* z(`Q2-0+cZ*o#vasmoGOjlagBC9uzq=i#0}Bz1=57-EF=`$E_e+ERLm%iVZbt_69AF zW&1vAc2T*29hvH!Q!xj$5gG+z|4VD*U)z_DN#b2(`f z;G;gP&gUh8`w#-*^xeUyoQ=TO9Cbm<$+_odsM244k;p&7m&@Uzca1KMhT_Tcs8A(@ zxI9xMgqW+1@A=ua;}}MiB3-mf!A*gw1U&DCnTzg3r!PLfAt)$jY66lGAHe|$gxG9< zpRfTr=hJ!QMaKt2R}Ef$bnIjna=~|}n*I+A>EHXqU+eW^@XIi{$`k%O*r?zy8eLGH zOrY&1l^$rCknx^uMwIttfS5nKN>7jd7JF%%KCF}5OGf)*--mKGyqYuSLm8|CS?KVW zy}tu-Y%YXT+48vj+zr%=?I-G|*h8IrT2(F^UpFDXa{!fidk%kujv7A4#Ar5@U7-U} zN_I58&e$_0VSng-x3H1^vKE{#|0_cj^TJz)q!cMrULjl>PCgictxQX_&(D?P05tT5 z^;3cj9bCI1E1b?&Y9v4}8M}KioKv3>Z0yXtw+%=O0U0CDXG4$k^hC-J7A=l)3$#nE?I-r3GkepOhcroq zmr1FS;gIeVZLl~Igrf_M<6&{1QaGuy;6lRm*y-(A4w{N!?FWdW@C4hoX$eS{}uo#0?7f77IklB|nUv{hRkmhTQr8+ER zrO$or;qCMH@H!dZQ7-iE+S)EY<-$0pRxo>mo?IZVqa)zvJO8smo@r79__Gi@_b9I#Db72;`pyQtB$>U`tk|zQ)?U3JN19y-ci6vOk%` zd8&qS>gzqLS{-(n=Kozbj-wi;e>n3sb-X?8f+u~>n;{*9f zD**XC`D~EVqmt#!uI7MYHbZ8n%*@TToku9&!R&dL;sU9;3Ez^8X?Ex zNOho=%wz*PEF|(WaEL{l>YY>%+%e`%lPC~rwjV^I!CuIv*d4&vd9e?aLn%d!Exk5Y zV*$lk9@roozJ|rH@c`v}d(U`Ld)zTena{|IFGq!DlZdDuC@mTwdY;`prVb~#<}}|e z5f`~0W7>4fWh-uhXT*spW;I5G{kEq6-BZ#^ zp8`eIMtIh9p@#;^vVC)By0%J^zQ{qiHsve#+iPaFO(IaNuReM(U)O@JM5~A22riS8 zPlevwpNxF#854^;dN_DCsL%iWmhbO0T8gW*m*~zhUX>lq+v1*yR6fVGdA`X@l@#Qc z{kKoY-)=b~l+#x7$F(%nnXumDx_MI~&cpr{4|m|Gz+AL>J-2c@@S0V(eROv>=45D^ zGA{hMI0I^UZwQE&$y`>)m_fI!$ov44GFEHi4iYAMGzmov-+ZtdmgFzkw#unhsM++9 z(u#{V_Rj)sNB;3i+>brx+=-c~y zd00w#@tPr!ZhaI)APRbxgv;&Li8mW5;zxh`oyI}7)-z7twA;tQe*z7}asnN?R@u?9 z5dW&JUG1RfuY`fb=PVUBXU--OJ^hSWJ4maoCbizWiN+{A+*v}?Zn?Nn-A+zHfWzu` zE!O74(e4r_7i91P^>4`x?f#+_ug|?`!$s#n{AEZlQBYH}f<6Ua^zkjA;Hw|Wx1(`V z+@%>zl$0lRyfQ7?h~5qBl!c3NaMXxX@|)xnsF*o42^?3^M&j+5&x%=OKAwET+uqv60|DMKp@KJM%Z>e~#w^_xZg_oibEPKL$l#b*3~?gC?q%5PSE z@N2T|EwtJ~a9i;hCA&4Uf?iLU0GwUOVdgVGQTY7%N!1Gy2@mlkVTV{4#0775!D-M1 zJJ_o`KH%HWzH_UbL95V6tB`@S(C-q{scT$sT?wwW-1ISIBz$oB#rn(zQbL1|Q}kc& zMYdiIdOmk&n4st?;k4m$upRjwe8R@_LBEIPq!_V}=RC<%S z&{CZ05++U!x&~c!SUbdu?Uc?q9P}K*o#>-8@#oOm%3P{sR;5wb(HOP0M!)|DULfqy96@>iGU=QqpNFT5L-LiI4tX8jil|kZGc1 zo1OwTJlmdAl;@z#xVc1vL&oo$iDHk?V(}EDX7)=tr5rg+PG;uP0oObAP`fzxMyvJO zV_(>H&zV@U7_q7OF=Ub3-hc}#7{g+E&>LQ3njwGOEV|ocyRW*`dOfd8FGp(B70-tv z-k2wpZ2zO)HLZi+&|Pt@wbHL&zeZYgUu0{X{^I!Ljq@PcZDhrVw_V02=_>(x@x}s7 zO4o{}RP$b>kTUtB9jZNZG8K)K2MRS3fwpU3p<{G_pWhjgl=txcGjDwgF{wr?ZQI`r zKA3yVL_UetzG^O#Z`$ZzI_9(zYVK2*cKx_z)Fr3o=1cKBd;*Bm9W?p*j;^lRHJ@>~ z6$D$>{H^1F6=M{N!i;T2c{JE~92rctGSTMMmeZ?Y(o-R+KW5No+jtf96dVy?Rz`<5 z{AxD*Fg~Ryxle) zvKPgpyUR#Y(Y-Gu-ux3V+=n5xjI#TA*{WY2s(`W_)_21dF;P7<`#CV%HQBmywPNtP zh*s+20vE7$$bqoAEj<*^BQLs@plwsl&PlXcnmQDikujN_KH03dhQ=T@8|BO&_~vmI zl^r0Fjm<54li&6h2L?qIOKoT~*?0tDtCnRzDYA(0(S^6i{9{-31YsP@?Qx08kU^Z( zwj<-n;H9g&Y~&-ASrg~eR?DH{_NNrr^{|pLj%PaQJ9RKOG^0 zv5bganh?9^7+_vu@?(Uk?tuJWsEDNGO2twxi4A1b#Rqp3k5gM9#_cIr35~^8>n(q4 zk=ZMcKNOEUtie=^RV{SdbTtEec@kxjeM8s9d9|sp8`D!+`cV3#CES+At2oAfKW7Gr zQ^*IoC}FSGT@Wo9OtI?k+b>wfxCf>+h2Z5hG&cCy=vAB~3QMI*8C;`j6RZrOM zmR=i*qv%%I)vIkE-t?!YrIFJO36h;z&=Eo2wjL!vA9H1hbvQHXLs*wdqomJ8nl4Z4 zw)1|=C1#w}jy1*U8H<*K{9$$bzB#qEsOlmy50w50rRZVWEDVFySVI+TpNemdQw=e% zJy_%Pk&Yi!E6IJUL4zcpz}DH`b37K`Yo#3{o!El;rNS>gNU*@8F6lOXAllmEX#uji zHddR*pP`G56l`NExK`BhLsu*k-N1hxmYwAAt@DXw?k}u-gy$Uh)L|`-upZEkrVt!Au#J0-&2uE*|tv{ztjTwu#lvm>NuXL8SWQoL+` zE;`s-3iL^Guw5Og+YHQw?4}WWv)GOiRAW}M0?h(zlCi)zzK75sn*A1hd9}0SK5f!`{O(h7E&UJYmP^2 z={RHZ-O`Rpm4)MIHx`#Osji%S~FxbJjR*L$sUtKrRK#G5# zsV8gWZBb%H8L^Qvt)Syx>b;m+j+OPP2DhVL&4UciU6HNm$1fe1ayStW3=9lBGaNna zX6{FH5q(n^-&w5GrzRjE*xZ*PPqU)&GSQDA)`#ToELLk@yzn+2W|C#fPVU;+PSBuy z+&z)c1lbH6fgQEAy(n`H=)~>RR$r0gDAm*6AGe{rh&rw-NxP+WQ3P-Nazb~yb`Wt_ zWOOufIEUXX?mn^<*F+$s!T%VO3R_svb3*)E=IehZ-5~w;+TmQ^Kppwn0(;COsaiAy z`*g1pbr8GWMZ4d#UNKZFItE#*p7Me1#ZCp|=G3OJho}&=#|kI*mdB!6ZRz%xZF=M)$8*t1hLXFkqogZ1@Z3icK60)?UVLC|C2tN}`(% z0v64vr6*ID&q2J@j^$Y*Y$bZU4uX|=- z)Le!}(c{?0gC_F5Y8=<^dKLXF_y_Qz<+HSqHR7q}8W)$n!J&)ZwVSClQ?%H+xb-i! zm7HUt)dY$w$UcpRwWBW&S4eVRq@u75?NjEvVel1Xk&@@06{J44)Diuesl?{hS9ZF5 zy;?1IVRe)-mVLfD+MR#(%WI$deTQ)fkqUpOqm6lm#!n7_rc187ktX$op1UUXVuzDH zg||L7NGS95DrbrW&tfgZmPQ|th+J7MNAvCn`)>Es9ZN5myF2wC9eG5=#dXDBn8p+f zJ=y4%7TvU%(p@{)I9iZn;d37fz&*r9F_T@+P*hg*4uEba$%o%_Ue?^3mlnJ1x!jDE zz{+J}YB12L@inZEyv>z@ubduJ%JsCzJ!mVr+O9L(hZD89w?`ZZHu5&I@y+|YBEpbe z1y^Ld|CQHDWh?M-pN!>7(JBYDYFJHPI43`Z^rIebEDN;=hy+A)~wi^m?X_wLW)RLVbit0!-4p!RmwU9f4jG#ombSgJJCL1%!E{$UA@ z36j}Sf=5S2satN(;ISE8ORYXn%1>shDNklQ9ChG&j50LAZgN8JrO(SMyZ4|}v;upI z5Tewg+n@C>z>b<>GXZDgkH(eXkihozjnB|YZ+&B0DM+ILz}$?osXGo)WrK{{Z>+xz z^&B}ME!(L3eAN2n;9^YHM#5WeUu7cIQ-RmlC!=e!^bbdprsQ^uvjKLPaw}LrI)xD*@@FoYO%XEPys?nEXi@#PgFz~}tT!-Ekrh`9#W7a%>x%D9unl`exH=D4O zX(k+a+zn5y(}=I2n!p75PHpMOUPzj5#|iKRizF; zkv*9eW`gTY`y4l<=yx^YYr?6iG%yFa1uMN+?-_u|)Y*TgUeDtm57 zO$)fS!HzR-ak{*bfPAQ5+f%e=VU7;f^1`B5T{p|cP00|K2>C{>uZ`tQeCv{oo8C_4 zuV$DRfuo7AjhYylYJ=^#p&E{5s_R|XCEVE3+roZ~-+v-^Z7&s$;5@I(m3J6!(@k&)kQ@cPlvL@RY?8(yy@N|UBDZ)G`;MSym5NnwOP(u zkq)E0M)&2VfHNYo8JQplU#id2+sQl%wFYKh2qFdSEm+CZftnIM{hYN>CM4utH?lp`V#?{-WOiRq9e{aHYDQb3i5wbNx>u!iN z5jryzr)7W3B;qw5d*^JaHsV1_ip=t%Ix*5O&*x z{?;Mmp+_YVB2=ACESFUks$V=&Nu79syc1wyE%pJaSzRJ%FiSq$Xp!L-9AV$!4t09! z=@5M!;GmVV2e!VgS8=a>tlK7mqV*sT4eID?7{W7uZbh zZRe*Xe z<)Xr??bmt1?h^Za6mB)OIom!pyoDGPd#M08HqU6zTkdP58RgMLw_aB(g|fq>nF^T* ziPuJGoYzLkwkNvN;yi>QL7%GI@+M-T-&{Od=hMaqQDUF;wUwo*;v>#hF#Y^O@>TG+ zpS=aDbIYfQHK@in2eLG_pyRHOqc~!YX&lRJr&8|l^HX%ii&1b?If~8?n1MKFcn>f0 zE^;qEu}HZ)>ptDFS|MWmsj!Q@g;0kcF<&tB_rcX5e%H875LB(OUNk)j|<4)bVDD-*d+8(=nm0<03>OpA z9?Bm|Ss1Ax{I%~T*Nli>-3^TK5$DK%ipqIK6--ugdue;9H}udFJz!Rm4`Uy3-!gNA zX;pX5xF7uH9@VX;^#zerI)44)b>S=4l`FGTO{WPPS}FW}3VM8X%Ll;BqwpWI*B<5- zj)@1LG}89l-j>%;ij#NvgTHG<|Mk^nJO}RZ`a1YTEt1L3?0&S4I4Wnr)T%$iF{Lcc zCq8H6xJ1pgzu|CgeqQQ~lyi#r{+;om9JCQHI&Ltj>d9y7+5fr?K$S>*&>A)ew&ccA%($*F=-gc;@+n)2I^VQ zZEf#B7)HACxmi_5DlrxL5X|Z`-2F!r8ER=D4mH^mBNf5LU#0i~AI+UhXQ@P_`dph|J6CFhiaV};v8$29gU~CqLEa(##KTJ7t!au_RYL&p5?NJ$URX#hOvC z6f4i7cVh*%Gy^*Y-R;O&mX$K8#~$;)p|%nJL~(Itypn$jGq~F_L3*{RNvc7fGnRyo zj-vj)GsllPCkYN-k&%)44(Kl1ra>o${OY4{O?j_O^Sr5#`$+SAnCtx0F1~g|>4Km&m6ot2L9;e^(RNf6q6oKTnW0jZuk6I;9 zp9ZlkmujEbI(lwyi-|^2Ny)oCyt#gMc|kf$<@f6A*=2-3B0oOkJ+n;<0cn2s=Z1Zl zco(WQI~Chh8HUYOMv?JCUEIeR3;9#hyXOJq^)~Q4MPXY1x_hl2aMIX1JS5y)`yl$d zMrho6+N7p%xn=6LP3w6-srdcl{IyWAs|4_sr|>TPQ=E5PoNmomCZ?|W+ibYB=Q%lK zQw0ZY@%0D4mlKs<=yhl1VPQMVa(t!HHx#|&iH?`_Uh)Zdd4bVD(gNlqj!W zyTD(&EOT$aenU?`Xp2Apj~_DB?@m}#Djn_EYrP||X*gVtTRoazTHB+opD(JVolBK& zh|Kf6Q?=|xV!T1Tp8UzW!B&sh%lk+uaZPT1iR55av(H8DWK-d_P^i$g?O)jvOkB(x zuBPIzq#C+?6ydOSKKwj|)(=+8Nv$X0{xkbcxqGFWcM1X7V7*O9KeqOB;tT3_Z3S^< zu3nc1sNZ>^Cfnl+PSJ63M0CDq=paRcp1ap zot!%zG?JQ9x2X>JWgZJWGp|-+>)LP-3k!`O9d_3)EqBLF4?(NC%3wq5xsU@wg6rKk ze+(v^!XNp)ETkIG0ufie&ziYSRRUzkW*e`$t2Kgr6T2Pd++~DlB7bDp(-qq=RrjS~ ziY%{;dwHT-2qzBE3vYDX@mwaf?EU+VJ0N$rMAeAk{DC92*rDexI!|T#u-v@%t&_`5 zDB;_;Z|iHI{BP)_ty^oeDrBMhO4WP!5vwll%ShXCE1d4tYvyFU#I)`X5moCucZBQ& zA$}tTcbu0|KKtbh-L+OO^R#1;B2~uPh*j^`LwR*a%b|B-p|n!*hnDxY*2T{CQD`fl zA9GvB+V+85Vtc2Ah%t>b{%jg8wsDzRXDe&-`5bx?zWnNXKF_59e6qf5373@^NoA@vWl`cCUv~2{U(mdH*ZXAla!JxLIaQ&9e zpLs78vv&^-QCL^6?AoqReqQDj-x*Tj!4Eq>?_}m4)boBCk>|bP&96j_6;jq9aAJ|wYxY#5+erN#dYTLg&%7c1RnGU zaNgf6uh8loU}L&II)*WtcFpM$4pqCNCTwG|^N>z=3^&Tk>u9Hd_t4ors4 zi?fh@zH_<$J|g@g5&BAJq$`Uy;^{zxsYopJi6x_BTEq09~cCX>_nW)&-MRIJ8!VsM;>vE;+SB~M;B?TU&@XuO5+r|Q!?ybpxl!Z@k> z{%d&i{Tt6h@pn->52jN2k7f$L1wO9e2}jo9f!VMi4P*Xz?RX{=_F*A|73N@QIJ2=_ zpTR`MoO=Hj*)^mxpUwwl)QgNn`kXYPK(vNzR zFB9nc$$s`PWYOyYkL5~FR$eM+e0uHs4tDm0wGTDi7Al7Hdk_6uKM02K!6e$vwMK*+ zY?gN2%}3+v^F)#NLSq1;Hs{vDBBornroo{#bS_7Rj~<#V(OB@CH&7pD9y z-{GZLlT+#4^;~ySI_63)~iL5 z)bD<^t=m%Z)Idl&oc?gTeNi#dP3;=&Nza6!fFuNRS)UW!K>e`jl89<-#4MYFGQy+D z#`u@7z3zo#tE!(Y{R=x<4&Ri)qlrYj%EJ#`7OXXTM1CKvYlvF&4hy=r9H_Nv^L*aF zm)F;ih(FAecD@$4|+ratIW9 zcs+Ecy|c8UqoR&>oVKE;q<(cE2i3((=rfsHt#9RV+VM|YDC@W)U)y<9MNcPMxNK3i z77Z45-*$Vz@I@)mvUbNgBV~VnetrmTYyuk~pZ^i)`TecIQ(v0PsLOv7Jy!K=ebF&D zSlKVtpoHPC&}3?*&ggD|bzL1s9BV>&0t}qP0xX1K3%&De2+j^z&*fkLjJ(&`U_ zpo{yhEc-Ej4+xH(L;2Z9m(Vu}rFcN+pxx9Z_I^ zHs*{ZA6(Ck4?fY%qt`yS#_UE*ozpEtTmRu*c4-9Jg+>S8th$z_LG9JTZ%H82DEQ)q zZ6+wS!gaCP`2_te4*2&Hiq^i7RZJOO!G#St(QM;6OlGMnpoQAv9O-Yg}&RRb83I|XI=A*yAr^w-(8W|Y_+}B&$z6Kvgqdr;c^s_eew{I1sPFu&Q zxOOTL`8lSO?GB&$=Jr@AW)1z=AV*tCcz4Lpfo;gWy=1?)&kvxw;q~=L;ox67C=@Ck z@)K6?8aMF2)!geL5R~_`)H|6{NfsI znZCr&B9*@;N8Q||i0JBrKmcgqFf%hV3(KS#XPe{H4JD-x68Huy$QJj6XVZ~UJCX&$ z$k|a3UCcNKPp?nOH=4sq#W~T^)?xdBW&_`SJ&dupq^LEd1b!txIyyQoBEr=&p>_>H zKuCz$+1Wv5p8n<8Lap}fx##NVR#sBlYn0{dgj!ZDp^eIcEcAsDJ8~tr=xEi(<`#31 z_f|`+@3!YGLSpsZk5gVm^=4Z%3fV=G&F#5fv*5y%OB%3V>gBbvtlk~gtd9L$aIERy z$&NsjE0L`AwaI? z`+dEy>jSsVxgSh>tS+vvcUK9VI?=U3a`(f4wXJP2eSJ#W)0r2K?jX+%3_O1h`czwu zeEl*V_rkEH4|z88dAf)lO`?z#kp`KIa4ZTwccM z+qruc4_D5Aq^SwoBuLMrEVES20l6i|C4X^ zko0(;&)-4REnCX1TecWZpQd>$#O?RL@MoIEU-vBwL?reo9qHHjhkKo%6oKk+A*mLzTeOG<=gYKi0nE{M^$u1nX!| zBB=f%agCWLXihA?u=8SF0-LRsOb(9~vdVLRS$|CH=uY155GSt}GMkot(ci0C5rokc zu?6D2)4o1JvOh?7F23gkTmMmP$J+PJ%zDZ_=`szx1_0sY3UJ#ZQdN_Eb68k&%i3Om zc5)ribab;?cpN={{_sj2Vn4&fv@KH_vR*k!)VC=4E#Z;NSrVWK;5DLl*Y~xF_S1p+ z(KZ@~lf!R z{boU^XCv*W#DwF-p|25Ry}~^hJE13%0AU~}=$MY~NyM04B7~SlQ?dW-Y(Kw`|I>x*b;v!FoN z-$r8LTH1XS7d3h^1)eZfRrmOaGz|Wat@f`Q=`e2P=?2=#Af2e26Qb zGBHZxXqY8bAcl^?h31F@KV)=u21OU>yb4?R91ZWsUbO>TlDu+qu<`-sVFi8JM)_Iq zk$)lVn?>Bt;+mW7)dLo-G;z?iw+ zZci&38bz2a?HTyZe-X<1TgKH8yFn#MCh)J@P@)!_r6zw$7t&O1G8Qp`QP2fV?fnN> zO_@z0sQsAwLC=)YErD0Bywx(1i$jSBLy`p!aH@raBl`xUHJ%-3dm_bI1R6-P8e7d8 z!D*to+P5n1kdZZ$P4*(n&HYZLem3Qtg!FnUITeRFLfTHS7Of%3gl;ZC%z5No_FGMQOFQjL z_`Q_kY+On_vTjRT{Q}E2X_T)j%|C0oXfSsW6i z16u`3OIg!%_de{EivXDKM7nT$EL(uk=VCa6u;4n&uKz0M%R&CU* zt*IW`i#~L!8wM6dzcX!WoD+KWWQPjid!~qb!oXM-qzxZ9V<^bdCCddZ^L@W0ABeTd zE#MjlBz&I>n$XFy!08)q^F6?$rJ4^1 z)H8c;O0Xh)=*WH#4SDg6UD6>+X_>ZbudFPmISeoC!6%X?UNx+E*#i%+ zZtBjjogS>1bOADW4MHg`fp(Q?5k?nRx8+^CCNpCP%9H{=ShI+lH_+MI8Z~E`1#>j1 ztFSGnB7L@$y!b={Yu78iwvR^og(QvUf$QC++wv)m1sj zmDb@8>Fi~`pS@@mfy<)x=+beMBP_RAvk#iT)jQIv`miGMmEWK7vNNhe|DbvAD)mV# zK#j%q3vuGGDcMMqLPQ_%!Li!gS4ipgxv*!K>@(K2~Y6ygE&c$Me& z^@26LOn2qAbOPE+EHSTpCv@csm9o|0c{?Gzx!hoNvizyH-fKL0`3N#53tS3xXZpo* zx>k_gr-Z=ye6xF%Be@m`uXi)id!j5yw;-sWGLm|^Njk?MmS5Dcuf`>O;9mKb>BFO* zh>Lb9u{bsrCqKqTKeFf7&m|BbJJ5g#C_4K6lw8o@;u(wmOkpQkM*g&Z@J?D zPsp+a!_k*XeLyKQHT(DRDTU4zLCPjL^rY=!;{si6C>R)%F?uDDXz08Q#ZUeO&9~LI zb7fuqbmfuBy|I026#rUr1y_c%P$n~} z2G?iI%8odMvPP$8=i6^fDy-HpGLXn|G zhjUMV<(9)s2vtS?koCa~rM7VlXdS>crWFFGf6SPXO$6!d^O_|;1rcqu%I4mRHe&2Sv;g9j6H+#c6Cry>SpFW1{a9CFnfx?Miq2}#N zE~1u6R7{A-cNVicmMo0Ksa^OaDbRUQntRz0X-+P(RIQ@mL9MIGTAa5s`PKV;|DHVK zJWtr{zryVB^x_SuxLWPEZ2@~~9GgBi+pLWQN(F%S5=Q@kWHKWchP#3$sT+As2S0;- zc7?uN1w!$5#7-_>_b^F-S1(-OIP-6R#(SOO1Um<=#lyWn<**c?k zxUff=Jj2jeKm~YmcW!#wgwnZtQ?m}jevFzaZCZ5UHt5;co1YuDJIF(YH?g9Re`$Vd zm!)(FCr1*yPy+%=_rmH}nL+SR=f9k~ zTukU&3#7${EE;7v-OaPMAi%ZrTDc{8-k4kt0AySBM=}G|lDO;!q?bKSdWbp7oQ3nChLtz9}Wt2PCH{>Z;HKVeT$LD&GC?G`RBDC8Z7fT7K~2!@n3yc=o$K@{`rAk8`uuaX zw%wKhQMq^meLx5?*~osS#t4D}G?T+B#8sG#fKHKLGy=rK^^p%1YEjjsjtlcm{V&9q zoYD}ds9V~gx8ej1fWoYxM}bQn;$9kN&xCP!e91jrdl7-cZK&nUyoVb&8yR2jXy`f!qDfR&=zKKb%;(SFk$F6HUgv-HqP6%3rC0v zv6CZka!Y#F91)UmOo{?2e)R^_GaowhtgReZ%&MTUt9*exZZS;uHB9ZjMfwI zd#tTp7G~JD$%L_~{nw=e-W+p5zL*&r2C6X?s#lS2P^=3N)l_sr$&jULN{Kg|YamA6 zzB=^zRUJ}CO$DBoWRNq62J*>sm&2+iJmx_thE-4WD??|MO7XD_l2HmJMbNTh|EThblj=y5EkK9n>`cS&-3s7;YahPdKb$}Z< z^Jj{+TF$GFhyIHI59YoR1U|*)_josCfL(nUfZbmYJD_1=?I~tE@GEOFGm0H*=17gI z8x480BkMG98dZzZ-XPyTiflQeWhQm*ZHNl#FEL8s?p9*>#w{(k^iOL%7+?(WKU^{e zq^huaToe>2FSE{Gsx8ow6i_UwLYeBE#ZiU6)wow$ywW&UYm->wF~C(y))MVAMw&ZM z8tbzlCiPl??v(W>US_j8CI$x_Hir?=2_D$9ncUf-%%hFaGjSE=D4f6BJnqjv3LB0# zJK(p7Yl-fxC*juJrGC61<)T|P+C|gdDrh9;blu|-^9L|ax>sSF^&=M~XOZbxWXx|b zDE>_szza7dVi7L9W%5A40f0#vMglD)mpN}g+p1yllQ}#}&>^WedW|rdx@1jO+=DkAWKb8H3FTkh}g$$ij1Km)enlkT<#Xns}e1qE|N1EG2>D9|Eq zI>57j^{MVS>}iy?a8M8sUehqQr~mn1=j>*>-WrO>NfDpubHAEd3XIV(70bDVhi&b#K6vjWl;tNgxujo9- z{rm*-@A`noJcSyHGxyHSGKhdi)5#RyT2O;zO3jqzL-x&9gm%4E(CS;s<;s8|!KuWL zw<=A~9ux)LNHFIZX>mm^PzFy!catd=hsPy>VH3R(_7u~LSGAHa9qjv-%_HE$Y(5Xj zTrN=dxJ;7>2C$&IWa12kHuESbkWCF`kob>}_#@$$ZKV@n-&nIJ zU9eTNQ=lTDL7-o=uXN=3|NnlA@t-Pi_~@o+I<_&7p{{xW6%#mF%@Zu81z3pMW>wvw z*P$r66;KyVp_Xap4QarBPfnBGj+5un)yxNmv4R?jG9X=GWEW+<50b+Y!RsO1>4k99 zGw+E3rl7-z;}!~}*2ry|aS z*aaOeK@R;*yb{WSbRXWBjm6_}brfzEuX^A!<-F&PN*z%frv6Wj`_fN)ImP?er?>2z z1aC)eA3LnGHZI8340W7kqpA()5j>-3{}PjZvlcNhURy8_m?P^*%DB736BOWy!o43m z+1mm;`VW5$IW57>bI7iD5g2#IHY7H?*wl;3X|iz|ZKlkzWc zubHiZ(F=O2rE_}S5aOJRbbtK~3G8oi_M45J8^Smq594Gd^@ssE-$3gyPq~U*X6FgeorFg^b^eHx`ok_A?-Hf1FOo&AnM6kWyx9WvES;}5WPQ#+q}xpT$gYC z?qx6hsvP(s&GlZ=rPeo3?AeeC{{p|dDNk<;DvArF59P3NYVGJ;_fLFHEdYOLyz0qk zHFEA&6D+2hIJ!KWTGXg+!-Gl1LU;q9PpWa3zj>Kf|L$r3U)RTd`Z)9CQQcZ9+03b1 zQ~}$Gmc*X(!0R9Fi!y`go)}e}9eQ>2TEXC}0O}X)3X)U;#rP}{OUVz> z2vl*Fc+Ot`@Vo!xj^=kyC!)(7^~)BTlhG%=!E_U;9{MOYY8rI^TAIFKsI$KY80ixj zygFOF_jtN>w^-N^H8H)4aRmkzO>ZOUza^^flAs8#qrzg?#974&VOk)}=;&0n&q3mf zE;^;pe&}_{h^M?yeIO}PEQ}zJnJ)rzL4?@@-_tP7`L5x=nUce&^Mog^VFj4{{HLhk z^M`{t_}7mjF~K-?XjiFih4QN+DoLSMsF|xVGd1bt>P47c_k4NQsWI(2+@?^^FU0w) zPwqV@H7+RBRlk8s&=Gs0dKNs=^J2^15AQZt9pzPt+RlOjr*CU&#NG%TdnxUr)@Qek zoXwT@Ej0Gu?~Dg5Qx*AvQ`vsX@Rr}cuLvG3{o{={TWzY5w2K$_+mM$;z+ze96T1XJ zR}!o(u5G-eVCK@$cXeTBXC#Zqa?XND9|ijkRVMAZhIIwjHes3+=SC$#+otnxA1$|T z&`K4@b+TTMbHy3`Z%7h~V}>NkoDjU|@sVwf=)cBYOAun()Bvo_`J7+w%#midRmw$z zTHKON5@@N3S*+{d<(zp_b?laIQ$>)YF;5OK87XDu-Jw2nK4w6m(4$Q7W7HZsKj9AW zoC8s>M-Pl|B)kqWuy$6`Go2_MiZhDfD1bUeRVKUCuv>G<{%7Z2rp@y)d>~4H$1kwK zO9Y5KAc?P4(VwT(>#HBo`@I?Y^;wfl5@8&DbOoVkKOSNb;e&rFF!0Z`#xY+Lt$A(a)4Q`5s5xM#WZ zhi`w6ua6=eh2c9)5e~H%W-{&!7Ur1YfMlXp+;V5V0aHEtBJ3CEAhWWm%jn%+7S$B7e&vXVwp1I-*)bLMuR4pA+?u{+c}*Ayf&lU#3{X?lG3VIV0_ktgYb zpTP{a)BY3zu*wWa)0cUrVJwI{OB~Y1{=um*a&F~Hly90

+

See screenshot on how to setup the Detekt plugin after installation. + + ![Detekt plugin setup][img_detekt] + **Commands** ```sh @@ -217,3 +224,5 @@ Destructive operations like `rm -rf`, `git commit`, and `git push` still require This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for more details. + +[img_detekt]: .github/img/detekt.png diff --git a/docs/transfer.md b/docs/transfer.md index 1a7c0a402..06671be7b 100644 --- a/docs/transfer.md +++ b/docs/transfer.md @@ -455,5 +455,5 @@ Transfers are serialized to JSON and included in backup. Restore deserializes an [^1]: Currently we can't display the channel closure transactions as 'transfer' yet in the activity list, due to an api missing in ldk-node. See comment in [ldk-node/wallet/mod.rs#L728-L738][ldk-node-comment] -[external-node-channel]: https://github.com/ovitrif/bitkit-docker#external-node-channel +[external-node-channel]: https://github.com/synonymdev/bitkit-docker#external-node-channel [ldk-node-comment]: https://github.com/lightningdevkit/ldk-node/blob/22a5d7742cf4e9265173ae51106db4bd9668ec8a/src/wallet/mod.rs#L728-L738 From a66feef7dccd27b9ab731467c493a58a7d605ad9 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 22:20:40 +0100 Subject: [PATCH 03/19] chore: cleanup --- app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt | 11 +++++------ .../ui/screens/wallets/send/SendQuickPayScreen.kt | 2 +- app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt | 2 +- .../main/java/to/bitkit/viewmodels/AppViewModel.kt | 8 +++----- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt index e6c122822..97c9aaafa 100644 --- a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt +++ b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt @@ -29,6 +29,7 @@ import to.bitkit.ui.LocalDrawerState import to.bitkit.ui.components.Title import to.bitkit.ui.theme.AppThemeSurface +@OptIn(ExperimentalMaterial3Api::class) @Composable @OptIn(ExperimentalMaterial3Api::class) fun AppTopBar( @@ -40,17 +41,15 @@ fun AppTopBar( ) { CenterAlignedTopAppBar( navigationIcon = { - if (onBackClick != null) { - BackNavIcon(onBackClick) - } + onBackClick?.let { BackNavIcon(it) } }, title = { - if (titleText != null) { + titleText?.let { text -> Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - icon?.let { painter -> + icon?.let { Icon( painter = painter, contentDescription = null, @@ -60,7 +59,7 @@ fun AppTopBar( .size(32.dp) ) } - Title(text = titleText, maxLines = 1) + Title(text = text, maxLines = 1) } } }, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendQuickPayScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendQuickPayScreen.kt index 186b85b88..bcaef17eb 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendQuickPayScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendQuickPayScreen.kt @@ -54,7 +54,7 @@ fun SendQuickPayScreen( DisposableEffect(Unit) { onDispose { - app.resetQuickPayData() + app.resetQuickPay() } } diff --git a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt index 5c4f49e59..c3fec1648 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt @@ -56,7 +56,7 @@ fun SendSheet( // always reset state on new user-initiated send if (startDestination == SendRoute.Recipient) { appViewModel.resetSendState() - appViewModel.resetQuickPayData() + appViewModel.resetQuickPay() } } Column( diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 8d7911bf1..ecb6a37f3 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -853,7 +853,7 @@ class AppViewModel @Inject constructor( private suspend fun handleScan(result: String) = withContext(bgDispatcher) { // always reset state on new scan resetSendState() - resetQuickPayData() + resetQuickPay() @Suppress("ForbiddenComment") // TODO: wrap `decode` from bindings in a `CoreService` method and call that one val scan = runCatching { decode(result) } @@ -1564,7 +1564,7 @@ class AppViewModel @Inject constructor( } } - fun resetQuickPayData() = _quickPayData.update { null } + fun resetQuickPay() = _quickPayData.update { null } /** Reselect utxos for current amount & speed then refresh fees using updated utxos */ private fun refreshOnchainSendIfNeeded() { @@ -1588,9 +1588,7 @@ class AppViewModel @Inject constructor( ) } .onSuccess { utxos -> - _sendUiState.update { - it.copy(selectedUtxos = utxos) - } + _sendUiState.update { it.copy(selectedUtxos = utxos) } } } refreshFeeEstimates() From fefa5a3c4b8fe20ea0ed08310331cf0acf730bf1 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 23:27:05 +0100 Subject: [PATCH 04/19] chore: fix warnings --- app/src/main/java/to/bitkit/data/AppDb.kt | 5 ++++- app/src/main/java/to/bitkit/ext/WebView.kt | 7 +++---- app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt | 11 +++++------ .../java/to/bitkit/ui/screens/wallets/HomeScreen.kt | 2 +- .../bitkit/ui/screens/wallets/SavingsWalletScreen.kt | 2 +- .../bitkit/ui/screens/wallets/SpendingWalletScreen.kt | 2 +- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/to/bitkit/data/AppDb.kt b/app/src/main/java/to/bitkit/data/AppDb.kt index 1763a3818..d67f22094 100644 --- a/app/src/main/java/to/bitkit/data/AppDb.kt +++ b/app/src/main/java/to/bitkit/data/AppDb.kt @@ -23,6 +23,7 @@ import to.bitkit.data.dao.TransferDao import to.bitkit.data.entities.ConfigEntity import to.bitkit.data.entities.TransferEntity import to.bitkit.data.typeConverters.StringListConverter +import to.bitkit.env.Env @Database( entities = [ @@ -53,7 +54,6 @@ abstract class AppDb : RoomDatabase() { private fun buildDatabase(context: Context): AppDb { return Room.databaseBuilder(context, AppDb::class.java, DB_NAME) .setJournalMode(JournalMode.TRUNCATE) - .fallbackToDestructiveMigration() // TODO remove in prod .addCallback(object : Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) @@ -65,6 +65,9 @@ abstract class AppDb : RoomDatabase() { } } }) + .apply { + if (Env.isDebug) fallbackToDestructiveMigration(dropAllTables = true) + } .build() } } diff --git a/app/src/main/java/to/bitkit/ext/WebView.kt b/app/src/main/java/to/bitkit/ext/WebView.kt index 806c637dc..5dae2f839 100644 --- a/app/src/main/java/to/bitkit/ext/WebView.kt +++ b/app/src/main/java/to/bitkit/ext/WebView.kt @@ -4,17 +4,16 @@ import android.annotation.SuppressLint import android.webkit.WebSettings import android.webkit.WebView -/** - * Configures WebView settings for basic web content display - */ -@SuppressLint("SetJavaScriptEnabled") fun WebView.configureForBasicWebContent() { settings.apply { + @SuppressLint("SetJavaScriptEnabled") javaScriptEnabled = true domStorageEnabled = true allowContentAccess = true allowFileAccess = false + @Suppress("DEPRECATION") allowUniversalAccessFromFileURLs = false + @Suppress("DEPRECATION") allowFileAccessFromFileURLs = false // Disable mixed content for security mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW diff --git a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt index 97c9aaafa..7b72984ad 100644 --- a/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt +++ b/app/src/main/java/to/bitkit/ui/scaffold/AppTopBar.kt @@ -1,5 +1,6 @@ package to.bitkit.ui.scaffold +import androidx.annotation.DrawableRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope @@ -16,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource @@ -31,12 +31,11 @@ import to.bitkit.ui.theme.AppThemeSurface @OptIn(ExperimentalMaterial3Api::class) @Composable -@OptIn(ExperimentalMaterial3Api::class) fun AppTopBar( titleText: String?, onBackClick: (() -> Unit)?, modifier: Modifier = Modifier, - icon: Painter? = null, + @DrawableRes icon: Int? = null, actions: @Composable (RowScope.() -> Unit) = {}, ) { CenterAlignedTopAppBar( @@ -51,7 +50,7 @@ fun AppTopBar( ) { icon?.let { Icon( - painter = painter, + painter = painterResource(icon), contentDescription = null, tint = Color.Unspecified, modifier = Modifier @@ -64,7 +63,7 @@ fun AppTopBar( } }, actions = actions, - colors = TopAppBarDefaults.centerAlignedTopAppBarColors( + colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, scrolledContainerColor = Color.Transparent, ), @@ -146,7 +145,7 @@ private fun Preview2() { AppTopBar( titleText = "Title And Icon", onBackClick = {}, - icon = painterResource(R.drawable.ic_ln_circle), + icon = R.drawable.ic_ln_circle, ) } } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt index 5e8a6c64d..a18fbfaef 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt @@ -679,7 +679,7 @@ private fun TopBar( ) } }, - colors = TopAppBarDefaults.largeTopAppBarColors(Color.Transparent), + colors = TopAppBarDefaults.topAppBarColors(Color.Transparent), modifier = Modifier.fillMaxWidth() ) } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt index d071dfe6d..cb3399fa2 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt @@ -82,7 +82,7 @@ fun SavingsWalletScreen( ScreenColumn(noBackground = true) { AppTopBar( titleText = stringResource(R.string.wallet__savings__title), - icon = painterResource(R.drawable.ic_btc_circle), + icon = R.drawable.ic_btc_circle, onBackClick = onBackClick, actions = { DrawerNavIcon() diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 82460dca1..201b4ea0a 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -84,7 +84,7 @@ fun SpendingWalletScreen( ScreenColumn(noBackground = true) { AppTopBar( titleText = stringResource(R.string.wallet__spending__title), - icon = painterResource(R.drawable.ic_ln_circle), + icon = R.drawable.ic_ln_circle, onBackClick = onBackClick, actions = { DrawerNavIcon() From 08dc1af9ddec429fe84da240ba6b2bd6223f9538 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 23:28:14 +0100 Subject: [PATCH 05/19] chore: add compose-stability-analyzer dependency --- app/build.gradle.kts | 2 ++ build.gradle.kts | 1 + gradle/libs.versions.toml | 2 ++ 3 files changed, 5 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4450eab5b..19caafb39 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -9,6 +9,7 @@ import java.util.Properties plugins { alias(libs.plugins.android.application) alias(libs.plugins.compose.compiler) + alias(libs.plugins.compose.stability.analyzer) alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.serialization) alias(libs.plugins.ksp) @@ -219,6 +220,7 @@ dependencies { androidTestImplementation(platform(libs.compose.bom)) implementation(libs.compose.material3) implementation(libs.compose.material.icons.extended) + implementation(libs.compose.runtime.tracing) implementation(libs.compose.ui) implementation(libs.compose.ui.graphics) implementation(libs.compose.ui.tooling.preview) diff --git a/build.gradle.kts b/build.gradle.kts index 3e0ebc458..6b4fab0da 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.compose.stability.analyzer) apply false alias(libs.plugins.google.services) apply false alias(libs.plugins.hilt.android) apply false // https://github.com/google/dagger/releases/ alias(libs.plugins.kotlin.android) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a95f687e5..9f7374b59 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,6 +28,7 @@ camera-view = { module = "androidx.camera:camera-view", version.ref = "camera" } compose-bom = { group = "androidx.compose", name = "compose-bom", version = "2025.12.00" } compose-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } compose-material3 = { module = "androidx.compose.material3:material3" } +compose-runtime-tracing = { module = "androidx.compose.runtime:runtime-tracing" } compose-ui = { group = "androidx.compose.ui", name = "ui" } compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } @@ -92,6 +93,7 @@ haze-materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = [plugins] android-application = { id = "com.android.application", version.ref = "agp" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +compose-stability-analyzer = { id = "com.github.skydoves.compose.stability.analyzer", version = "0.6.6" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } google-services = { id = "com.google.gms.google-services", version = "4.4.4" } hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } From 9e8d5eae09f0292db54f912d764c3205d97ac4a0 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 5 Jan 2026 23:28:21 +0100 Subject: [PATCH 06/19] chore: update agp --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9f7374b59..0489a314e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.12.0" +agp = "8.13.2" camera = "1.5.2" detekt = "1.23.8" hilt = "2.57.2" From 6f9fa8f856e304abf7de798b07b0ec036caa4b38 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 00:01:21 +0100 Subject: [PATCH 07/19] chore: update env --- app/src/main/java/to/bitkit/env/Env.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 2fbbb680a..9e985f8e6 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -51,11 +51,11 @@ internal object Env { val electrumServerUrl: String get() { - if (isE2eTest && e2eBackend == "local") return ElectrumServers.REGTEST.LOCAL + val isE2eLocal = isE2eTest && e2eBackend == "local" return when (network) { - Network.REGTEST -> ElectrumServers.REGTEST.STAGING - Network.TESTNET -> ElectrumServers.TESTNET Network.BITCOIN -> ElectrumServers.MAINNET.FULCRUM + Network.REGTEST -> if (isE2eLocal) ElectrumServers.REGTEST.LOCAL else ElectrumServers.REGTEST.STAG + Network.TESTNET -> ElectrumServers.TESTNET else -> TODO("${network.name} network not implemented") } } @@ -220,11 +220,10 @@ object Peers { private object ElectrumServers { object MAINNET { const val FULCRUM = "ssl://fulcrum.bitkit.blocktank.to:8900" - const val ESPLORA = "ssl://34.65.252.32:18484" } object REGTEST { - const val STAGING = "tcp://34.65.252.32:18483" + const val STAG = "tcp://34.65.252.32:18483" const val LOCAL = "tcp://127.0.0.1:60001" } From 464a2f48efe1025bbb21afa0ef3d0e751aafe1e2 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 01:42:06 +0100 Subject: [PATCH 08/19] chore: update ai rules --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index e70f3c16a..a8a9f9ffe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -195,7 +195,7 @@ suspend fun getData(): Result = withContext(Dispatchers.IO) { - ALWAYS be mindful of thread safety when working with mutable lists & state - ALWAYS split screen composables into parent accepting viewmodel + inner private child accepting state and callbacks `Content()` - ALWAYS name lambda parameters in a composable function using present tense, NEVER use past tense -- ALWAYS list 3 suggested commit messages after implementation work for the entire set of uncommitted changes +- ALWAYS list 3 suggested commit messages after implementation work for ALL uncommitted changes - NEVER use `wheneverBlocking` in unit test expression body functions wrapped in a `= test {}` lambda - ALWAYS wrap unit tests `setUp` methods mocking suspending calls with `runBlocking`, e.g `setUp() = runBlocking { }` - ALWAYS add business logic to Repository layer via methods returning `Result` and use it in ViewModels From 64be2d3dab010d1a3154e66c2896ab87466aabe3 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 01:45:25 +0100 Subject: [PATCH 09/19] fix: replace WalletRepo uiState with repo states --- .../wallets/send/SendAmountContentTest.kt | 34 +++---- app/src/main/java/to/bitkit/env/Env.kt | 2 - app/src/main/java/to/bitkit/ui/ContentView.kt | 12 +-- .../main/java/to/bitkit/ui/NodeInfoScreen.kt | 98 +++++++++---------- .../screens/transfer/SavingsAdvancedScreen.kt | 4 +- .../screens/transfer/SavingsConfirmScreen.kt | 4 +- .../external/ExternalConnectionScreen.kt | 2 +- .../bitkit/ui/screens/wallets/HomeScreen.kt | 15 ++- .../screens/wallets/SpendingWalletScreen.kt | 22 ++--- .../wallets/receive/ReceiveAmountScreen.kt | 4 +- .../wallets/receive/ReceiveQrScreen.kt | 50 ++++++---- .../screens/wallets/receive/ReceiveSheet.kt | 5 +- .../screens/wallets/send/SendAmountScreen.kt | 23 +++-- .../ui/settings/BlocktankRegtestScreen.kt | 4 +- .../settings/lightning/ChannelDetailScreen.kt | 5 +- .../java/to/bitkit/ui/sheets/SendSheet.kt | 8 +- .../java/to/bitkit/viewmodels/AppViewModel.kt | 2 +- .../to/bitkit/viewmodels/WalletViewModel.kt | 56 +---------- 18 files changed, 147 insertions(+), 203 deletions(-) diff --git a/app/src/androidTest/java/to/bitkit/ui/screens/wallets/send/SendAmountContentTest.kt b/app/src/androidTest/java/to/bitkit/ui/screens/wallets/send/SendAmountContentTest.kt index cf0cb569f..2bde503cf 100644 --- a/app/src/androidTest/java/to/bitkit/ui/screens/wallets/send/SendAmountContentTest.kt +++ b/app/src/androidTest/java/to/bitkit/ui/screens/wallets/send/SendAmountContentTest.kt @@ -7,9 +7,6 @@ import androidx.compose.ui.test.performClick import org.junit.Rule import org.junit.Test import to.bitkit.models.NodeLifecycleState -import to.bitkit.models.PrimaryDisplay -import to.bitkit.repositories.CurrencyState -import to.bitkit.viewmodels.MainUiState import to.bitkit.viewmodels.SendMethod import to.bitkit.viewmodels.SendUiState import to.bitkit.viewmodels.previewAmountInputViewModel @@ -19,22 +16,20 @@ class SendAmountContentTest { @get:Rule val composeTestRule = createComposeRule() - private val testUiState = SendUiState( + private val uiState = SendUiState( payMethod = SendMethod.LIGHTNING, amount = 100u, isUnified = true ) - private val testWalletState = MainUiState( - nodeLifecycleState = NodeLifecycleState.Running - ) + private val nodeLifecycleState = NodeLifecycleState.Running @Test fun whenScreenLoaded_shouldShowAllComponents() { composeTestRule.setContent { SendAmountContent( - walletUiState = testWalletState, - uiState = testUiState, + nodeLifecycleState = nodeLifecycleState, + uiState = uiState, amountInputViewModel = previewAmountInputViewModel(), ) } @@ -51,10 +46,8 @@ class SendAmountContentTest { fun whenNodeNotRunning_shouldShowSyncView() { composeTestRule.setContent { SendAmountContent( - walletUiState = MainUiState( - nodeLifecycleState = NodeLifecycleState.Initializing - ), - uiState = testUiState, + nodeLifecycleState = nodeLifecycleState, + uiState = uiState, amountInputViewModel = previewAmountInputViewModel(), ) } @@ -68,15 +61,14 @@ class SendAmountContentTest { var eventTriggered = false composeTestRule.setContent { SendAmountContent( - walletUiState = testWalletState, - uiState = testUiState, + nodeLifecycleState = nodeLifecycleState, + uiState = uiState, amountInputViewModel = previewAmountInputViewModel(), onClickPayMethod = { eventTriggered = true } ) } - composeTestRule.onNodeWithTag("AssetButton-switch") - .performClick() + composeTestRule.onNodeWithTag("AssetButton-switch").performClick() assert(eventTriggered) } @@ -86,8 +78,8 @@ class SendAmountContentTest { var eventTriggered = false composeTestRule.setContent { SendAmountContent( - walletUiState = testWalletState, - uiState = testUiState, + nodeLifecycleState = nodeLifecycleState, + uiState = uiState, amountInputViewModel = previewAmountInputViewModel(), onContinue = { eventTriggered = true } ) @@ -103,8 +95,8 @@ class SendAmountContentTest { fun whenAmountInvalid_continueButtonShouldBeDisabled() { composeTestRule.setContent { SendAmountContent( - walletUiState = testWalletState, - uiState = testUiState.copy(amount = 0u), + nodeLifecycleState = nodeLifecycleState, + uiState = uiState.copy(amount = 0u), amountInputViewModel = previewAmountInputViewModel(), ) } diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 9e985f8e6..c725f6884 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -206,8 +206,6 @@ object Defaults { * required to include them in a block would be greater than the value of the transaction itself. * */ const val dustLimit = 546u - - } object Peers { diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 36da5c814..3d7e786f8 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -381,9 +381,9 @@ fun ContentView( } is Sheet.Receive -> { - val walletUiState by walletViewModel.uiState.collectAsState() + val walletState by walletViewModel.walletState.collectAsState() ReceiveSheet( - walletState = walletUiState, + walletState = walletState, navigateToExternalConnection = { navController.navigate(ExternalConnection()) appViewModel.hideSheet() @@ -760,7 +760,7 @@ private fun NavGraphBuilder.home( drawerState: DrawerState, ) { composable { - val uiState by walletViewModel.uiState.collectAsStateWithLifecycle() + val isRefreshing by walletViewModel.isRefreshing.collectAsStateWithLifecycle() val isRecoveryMode by walletViewModel.isRecoveryMode.collectAsStateWithLifecycle() val hazeState = rememberHazeState() @@ -776,7 +776,7 @@ private fun NavGraphBuilder.home( .hazeSource(hazeState) ) { HomeScreen( - mainUiState = uiState, + isRefreshing = isRefreshing, drawerState = drawerState, rootNavController = navController, walletNavController = navController, @@ -816,11 +816,11 @@ private fun NavGraphBuilder.home( exitTransition = { Transitions.slideOutHorizontally }, ) { val hasSeenSavingsIntro by settingsViewModel.hasSeenSavingsIntro.collectAsStateWithLifecycle() - val uiState by walletViewModel.uiState.collectAsStateWithLifecycle() + val lightningState by walletViewModel.lightningState.collectAsStateWithLifecycle() val lightningActivities by activityListViewModel.lightningActivities.collectAsStateWithLifecycle() SpendingWalletScreen( - uiState = uiState, + channels = lightningState.channels, lightningActivities = lightningActivities.orEmpty(), onAllActivityButtonClick = { navController.navigateToAllActivity() }, onActivityItemClick = { navController.navigateToActivityItem(it) }, diff --git a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt index d79765303..eef545a3f 100644 --- a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt +++ b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt @@ -48,6 +48,7 @@ import to.bitkit.ext.uri import to.bitkit.models.NodeLifecycleState import to.bitkit.models.Toast import to.bitkit.models.formatToModernDisplay +import to.bitkit.repositories.LightningState import to.bitkit.ui.components.BodyM import to.bitkit.ui.components.Caption import to.bitkit.ui.components.ChannelStatusUi @@ -66,7 +67,6 @@ import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import to.bitkit.ui.utils.copyToClipboard import to.bitkit.ui.utils.withAccent -import to.bitkit.viewmodels.MainUiState import kotlin.time.Clock.System.now import kotlin.time.ExperimentalTime @@ -79,14 +79,14 @@ fun NodeInfoScreen( val settings = settingsViewModel ?: return val context = LocalContext.current - val uiState by wallet.uiState.collectAsStateWithLifecycle() + val isRefreshing by wallet.isRefreshing.collectAsStateWithLifecycle() val isDevModeEnabled by settings.isDevModeEnabled.collectAsStateWithLifecycle() val lightningState by wallet.lightningState.collectAsStateWithLifecycle() Content( - uiState = uiState, + lightningState = lightningState, + isRefreshing = isRefreshing, isDevModeEnabled = isDevModeEnabled, - balanceDetails = lightningState.balances, onBack = { navController.popBackStack() }, onRefresh = { wallet.onPullToRefresh() }, onDisconnectPeer = { wallet.disconnectPeer(it) }, @@ -103,9 +103,9 @@ fun NodeInfoScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable private fun Content( - uiState: MainUiState, + lightningState: LightningState, + isRefreshing: Boolean = false, isDevModeEnabled: Boolean, - balanceDetails: BalanceDetails? = null, onBack: () -> Unit = {}, onRefresh: () -> Unit = {}, onDisconnectPeer: (PeerDetails) -> Unit = {}, @@ -118,7 +118,7 @@ private fun Content( actions = { DrawerNavIcon() }, ) PullToRefreshBox( - isRefreshing = uiState.isRefreshing, + isRefreshing = isRefreshing, onRefresh = onRefresh, ) { Column( @@ -127,17 +127,17 @@ private fun Content( .verticalScroll(rememberScrollState()) ) { NodeIdSection( - nodeId = uiState.nodeId, + nodeId = lightningState.nodeId, onCopy = onCopy, ) if (isDevModeEnabled) { NodeStateSection( - nodeLifecycleState = uiState.nodeLifecycleState, - nodeStatus = uiState.nodeStatus, + nodeLifecycleState = lightningState.nodeLifecycleState, + nodeStatus = lightningState.nodeStatus, ) - balanceDetails?.let { details -> + lightningState.balances?.let { details -> WalletBalancesSection(balanceDetails = details) if (details.lightningBalances.isNotEmpty()) { @@ -145,16 +145,16 @@ private fun Content( } } - if (uiState.channels.isNotEmpty()) { + if (lightningState.channels.isNotEmpty()) { ChannelsSection( - channels = uiState.channels, + channels = lightningState.channels, onCopy = onCopy, ) } - if (uiState.peers.isNotEmpty()) { + if (lightningState.peers.isNotEmpty()) { PeersSection( - peers = uiState.peers, + peers = lightningState.peers, onDisconnectPeer = onDisconnectPeer, onCopy = onCopy, ) @@ -457,7 +457,7 @@ private fun Preview() { AppThemeSurface { Content( isDevModeEnabled = false, - uiState = MainUiState( + lightningState = LightningState( nodeId = "0348a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", ), ) @@ -472,7 +472,7 @@ private fun PreviewDevMode() { val syncTime = now().epochSeconds.toULong() Content( isDevModeEnabled = true, - uiState = MainUiState( + lightningState = LightningState( nodeLifecycleState = NodeLifecycleState.Running, nodeStatus = NodeStatus( isRunning = true, @@ -519,40 +519,40 @@ private fun PreviewDevMode() { inboundHtlcMaximumMsat = 200000000UL, ), ), - ), - balanceDetails = BalanceDetails( - totalOnchainBalanceSats = 1000000UL, - spendableOnchainBalanceSats = 900000UL, - totalAnchorChannelsReserveSats = 50000UL, - totalLightningBalanceSats = 500000UL, - lightningBalances = listOf( - LightningBalance.ClaimableOnChannelClose( - channelId = "abc123def456789012345678901234567890123456789012345678901234567890", - counterpartyNodeId = "0248a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", - amountSatoshis = 250000UL, - transactionFeeSatoshis = 1000UL, - outboundPaymentHtlcRoundedMsat = 0UL, - outboundForwardedHtlcRoundedMsat = 0UL, - inboundClaimingHtlcRoundedMsat = 0UL, - inboundHtlcRoundedMsat = 0UL, - ), - LightningBalance.ClaimableAwaitingConfirmations( - channelId = "def456789012345678901234567890123456789012345678901234567890abc123", - counterpartyNodeId = "0348a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", - amountSatoshis = 150000UL, - confirmationHeight = 850005U, - source = BalanceSource.COUNTERPARTY_FORCE_CLOSED, - ), - LightningBalance.MaybeTimeoutClaimableHtlc( - channelId = "789012345678901234567890123456789012345678901234567890abc123def456", - counterpartyNodeId = "0448a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", - amountSatoshis = 100000UL, - claimableHeight = 850010U, - paymentHash = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - outboundPayment = true, + balances = BalanceDetails( + totalOnchainBalanceSats = 1000000UL, + spendableOnchainBalanceSats = 900000UL, + totalAnchorChannelsReserveSats = 50000UL, + totalLightningBalanceSats = 500000UL, + lightningBalances = listOf( + LightningBalance.ClaimableOnChannelClose( + channelId = "abc123def456789012345678901234567890123456789012345678901234567890", + counterpartyNodeId = "0248a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", + amountSatoshis = 250000UL, + transactionFeeSatoshis = 1000UL, + outboundPaymentHtlcRoundedMsat = 0UL, + outboundForwardedHtlcRoundedMsat = 0UL, + inboundClaimingHtlcRoundedMsat = 0UL, + inboundHtlcRoundedMsat = 0UL, + ), + LightningBalance.ClaimableAwaitingConfirmations( + channelId = "def456789012345678901234567890123456789012345678901234567890abc123", + counterpartyNodeId = "0348a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", + amountSatoshis = 150000UL, + confirmationHeight = 850005U, + source = BalanceSource.COUNTERPARTY_FORCE_CLOSED, + ), + LightningBalance.MaybeTimeoutClaimableHtlc( + channelId = "789012345678901234567890123456789012345678901234567890abc123def456", + counterpartyNodeId = "0448a2b7c2d3f4e5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9", + amountSatoshis = 100000UL, + claimableHeight = 850010U, + paymentHash = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + outboundPayment = true, + ), ), + pendingBalancesFromChannelClosures = listOf(), ), - pendingBalancesFromChannelClosures = listOf(), ), ) } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsAdvancedScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsAdvancedScreen.kt index ef77ad01d..b72503af6 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsAdvancedScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsAdvancedScreen.kt @@ -53,8 +53,8 @@ fun SavingsAdvancedScreen( val wallet = walletViewModel ?: return val transfer = transferViewModel ?: return - val walletState by wallet.uiState.collectAsStateWithLifecycle() - val openChannels = walletState.channels.filterOpen() + val lightningState by wallet.lightningState.collectAsStateWithLifecycle() + val openChannels = lightningState.channels.filterOpen() var selectedChannelIds by remember { mutableStateOf(setOf()) } diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsConfirmScreen.kt index 4aeeac17a..f7351c939 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SavingsConfirmScreen.kt @@ -54,8 +54,8 @@ fun SavingsConfirmScreen( val transfer = transferViewModel ?: return val wallet = walletViewModel ?: return - val walletState by wallet.uiState.collectAsStateWithLifecycle() - val openChannels = walletState.channels.filterOpen() + val lightningState by wallet.lightningState.collectAsStateWithLifecycle() + val openChannels = lightningState.channels.filterOpen() val hasMultiple = openChannels.size > 1 diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt index fcc0a07f7..2fe68d868 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConnectionScreen.kt @@ -35,9 +35,9 @@ import androidx.lifecycle.SavedStateHandle import kotlinx.coroutines.flow.filterNotNull import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.R -import to.bitkit.ext.of import to.bitkit.ext.getClipboardText import to.bitkit.ext.host +import to.bitkit.ext.of import to.bitkit.ext.port import to.bitkit.ui.Routes import to.bitkit.ui.components.BodyM diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt index a18fbfaef..dd5f376c9 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt @@ -115,13 +115,12 @@ import to.bitkit.ui.theme.Colors import to.bitkit.ui.utils.withAccent import to.bitkit.viewmodels.ActivityListViewModel import to.bitkit.viewmodels.AppViewModel -import to.bitkit.viewmodels.MainUiState import to.bitkit.viewmodels.SettingsViewModel import to.bitkit.viewmodels.WalletViewModel @Composable fun HomeScreen( - mainUiState: MainUiState, + isRefreshing: Boolean, drawerState: DrawerState, rootNavController: NavController, walletNavController: NavHostController, @@ -157,7 +156,7 @@ fun HomeScreen( } Content( - mainUiState = mainUiState, + isRefreshing = isRefreshing, homeUiState = homeUiState, rootNavController = rootNavController, walletNavController = walletNavController, @@ -279,7 +278,7 @@ fun HomeScreen( @OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class) @Composable private fun Content( - mainUiState: MainUiState, + isRefreshing: Boolean, homeUiState: HomeUiState, rootNavController: NavController, walletNavController: NavController, @@ -313,11 +312,11 @@ private fun Content( val pullToRefreshState = rememberPullToRefreshState() PullToRefreshBox( state = pullToRefreshState, - isRefreshing = mainUiState.isRefreshing, + isRefreshing = isRefreshing, onRefresh = onRefresh, indicator = { Indicator( - isRefreshing = mainUiState.isRefreshing, + isRefreshing = isRefreshing, state = pullToRefreshState, modifier = Modifier .padding(top = heightStatusBar) @@ -709,7 +708,7 @@ private fun Preview() { AppThemeSurface { Box { Content( - mainUiState = MainUiState(), + isRefreshing = false, homeUiState = HomeUiState( showWidgets = true, ), @@ -733,7 +732,7 @@ private fun PreviewEmpty() { AppThemeSurface { Box { Content( - mainUiState = MainUiState(), + isRefreshing = false, homeUiState = HomeUiState( showEmptyState = true, ), diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 201b4ea0a..5d659ce1b 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.synonym.bitkitcore.Activity +import org.lightningdevkit.ldknode.ChannelDetails import to.bitkit.R import to.bitkit.ext.createChannelDetails import to.bitkit.models.BalanceState @@ -43,11 +44,10 @@ import to.bitkit.ui.screens.wallets.activity.utils.previewLightningActivityItems import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import to.bitkit.ui.utils.withAccent -import to.bitkit.viewmodels.MainUiState @Composable fun SpendingWalletScreen( - uiState: MainUiState, + channels: List, lightningActivities: List, onAllActivityButtonClick: () -> Unit, onActivityItemClick: (String) -> Unit, @@ -61,9 +61,9 @@ fun SpendingWalletScreen( val hasActivity = lightningActivities.isNotEmpty() mutableStateOf(hasLnFunds && !hasActivity) } - val canTransfer by remember(balances.totalLightningSats, uiState.channels.size) { + val canTransfer by remember(balances.totalLightningSats, channels.size) { val hasLnBalance = balances.totalLightningSats > 0uL - val hasChannels = uiState.channels.isNotEmpty() + val hasChannels = channels.isNotEmpty() mutableStateOf(hasLnBalance && hasChannels) } @@ -153,9 +153,7 @@ private fun Preview() { AppThemeSurface { Box { SpendingWalletScreen( - uiState = MainUiState( - channels = listOf(createChannelDetails()) - ), + channels = listOf(createChannelDetails()), lightningActivities = previewLightningActivityItems(), onAllActivityButtonClick = {}, onActivityItemClick = {}, @@ -175,9 +173,7 @@ private fun PreviewTransfer() { AppThemeSurface { Box { SpendingWalletScreen( - uiState = MainUiState( - channels = listOf(createChannelDetails()) - ), + channels = listOf(createChannelDetails()), lightningActivities = previewLightningActivityItems(), onAllActivityButtonClick = {}, onActivityItemClick = {}, @@ -200,9 +196,7 @@ private fun PreviewNoActivity() { AppThemeSurface { Box { SpendingWalletScreen( - uiState = MainUiState( - channels = listOf(createChannelDetails()) - ), + channels = listOf(createChannelDetails()), lightningActivities = emptyList(), onAllActivityButtonClick = {}, onActivityItemClick = {}, @@ -222,7 +216,7 @@ private fun PreviewEmpty() { AppThemeSurface { Box { SpendingWalletScreen( - uiState = MainUiState(), + channels = emptyList(), lightningActivities = emptyList(), onAllActivityButtonClick = {}, onActivityItemClick = {}, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveAmountScreen.kt index f88eba327..15ecf20d8 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveAmountScreen.kt @@ -65,7 +65,7 @@ fun ReceiveAmountScreen( val app = appViewModel ?: return val wallet = walletViewModel ?: return val blocktank = blocktankViewModel ?: return - val walletState by wallet.uiState.collectAsStateWithLifecycle() + val lightningState by wallet.lightningState.collectAsStateWithLifecycle() val amountInputUiState by amountInputViewModel.uiState.collectAsStateWithLifecycle() var isCreatingInvoice by remember { mutableStateOf(false) } @@ -90,7 +90,7 @@ fun ReceiveAmountScreen( scope.launch { isCreatingInvoice = true runCatching { - require(walletState.nodeLifecycleState == NodeLifecycleState.Running) { + require(lightningState.nodeLifecycleState == NodeLifecycleState.Running) { "Should not be able to land on this screen if the node is not running." } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt index 09484c735..8b48768e4 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveQrScreen.kt @@ -56,6 +56,8 @@ import to.bitkit.R import to.bitkit.ext.setClipboardText import to.bitkit.ext.truncate import to.bitkit.models.NodeLifecycleState +import to.bitkit.repositories.LightningState +import to.bitkit.repositories.WalletState import to.bitkit.ui.components.BodyM import to.bitkit.ui.components.BodyS import to.bitkit.ui.components.BottomSheetPreview @@ -77,14 +79,14 @@ import to.bitkit.ui.theme.AppShapes import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import to.bitkit.ui.utils.withAccent -import to.bitkit.viewmodels.MainUiState @Suppress("CyclomaticComplexMethod") @OptIn(FlowPreview::class) @Composable fun ReceiveQrScreen( cjitInvoice: String?, - walletState: MainUiState, + walletState: WalletState, + lightningState: LightningState, onClickEditInvoice: () -> Unit, onClickReceiveCjit: () -> Unit, modifier: Modifier = Modifier, @@ -93,7 +95,7 @@ fun ReceiveQrScreen( SetMaxBrightness() val haptic = LocalHapticFeedback.current - val hasUsableChannels = walletState.channels.any { it.isChannelReady } + val hasUsableChannels = lightningState.channels.any { it.isChannelReady } var showDetails by remember { mutableStateOf(false) } @@ -113,7 +115,7 @@ fun ReceiveQrScreen( walletState.bolt11, walletState.onchainAddress, cjitInvoice, - walletState.nodeLifecycleState + lightningState.nodeLifecycleState ) { visibleTabs.associateWith { tab -> getInvoiceForTab( @@ -121,7 +123,7 @@ fun ReceiveQrScreen( bip21 = walletState.bip21, bolt11 = walletState.bolt11, cjitInvoice = cjitInvoice, - isNodeRunning = walletState.nodeLifecycleState.isRunning(), + isNodeRunning = lightningState.nodeLifecycleState.isRunning(), onchainAddress = walletState.onchainAddress ) } @@ -174,9 +176,9 @@ fun ReceiveQrScreen( } } - val showingCjitOnboarding = remember(walletState, cjitInvoice, hasUsableChannels) { + val showingCjitOnboarding = remember(lightningState, cjitInvoice, hasUsableChannels) { !hasUsableChannels && - walletState.nodeLifecycleState.isRunning() && + lightningState.nodeLifecycleState.isRunning() && cjitInvoice.isNullOrEmpty() } @@ -273,7 +275,7 @@ fun ReceiveQrScreen( Spacer(Modifier.height(24.dp)) - AnimatedVisibility(visible = walletState.nodeLifecycleState.isRunning()) { + AnimatedVisibility(visible = lightningState.nodeLifecycleState.isRunning()) { val showCjitButton = showingCjitOnboarding && selectedTab == ReceiveTab.SPENDING PrimaryButton( text = stringResource( @@ -467,7 +469,7 @@ fun CjitOnBoardingView(modifier: Modifier = Modifier) { @Composable private fun ReceiveDetailsView( tab: ReceiveTab, - walletState: MainUiState, + walletState: WalletState, cjitInvoice: String?, onClickEditInvoice: () -> Unit, modifier: Modifier = Modifier, @@ -639,9 +641,11 @@ private fun PreviewSavingsMode() { BottomSheetPreview { ReceiveQrScreen( cjitInvoice = null, - walletState = MainUiState( - nodeLifecycleState = NodeLifecycleState.Running, + walletState = WalletState( onchainAddress = "bcrt1qfserxgtuesul4m9zva56wzk849yf9l8rk4qy0l", + ), + lightningState = LightningState( + nodeLifecycleState = NodeLifecycleState.Running, channels = emptyList() ), onClickEditInvoice = {}, @@ -703,9 +707,7 @@ private fun PreviewAutoMode() { BottomSheetPreview { ReceiveQrScreen( cjitInvoice = null, - walletState = MainUiState( - nodeLifecycleState = NodeLifecycleState.Running, - channels = listOf(mockChannel), + walletState = WalletState( onchainAddress = "bcrt1qfserxgtuesul4m9zva56wzk849yf9l8rk4qy0l", bolt11 = "lnbcrt500u1pn7umn7pp5x0s9lt9fwrff6rp70pz3guwnjgw97sjuv79vhx9n2ps8q6tcdehhxapqd9h8vmmfv" + "djjqen0wgsyqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxq", @@ -713,6 +715,10 @@ private fun PreviewAutoMode() { "lnbcrt500u1pn7umn7pp5x0s9lt9fwrff6rp70pz3guwnjgw97sjuv79vhx9n2ps8q6tcdehhxapqd9h8vmmfv" + "djjqen0wgsyqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxq", ), + lightningState = LightningState( + nodeLifecycleState = NodeLifecycleState.Running, + channels = listOf(mockChannel), + ), onClickEditInvoice = {}, modifier = Modifier.sheetHeight(), initialTab = ReceiveTab.AUTO, @@ -771,12 +777,14 @@ private fun PreviewSpendingMode() { BottomSheetPreview { ReceiveQrScreen( cjitInvoice = null, - walletState = MainUiState( - nodeLifecycleState = NodeLifecycleState.Running, - channels = listOf(mockChannel), + walletState = WalletState( bolt11 = "lnbcrt500u1pn7umn7pp5x0s9lt9fwrff6rp70pz3guwnjgw97sjuv79vhx9n2ps8q6tcdehhxapqd9h8vmmfv" + "djjqen0wgsyqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxqcrqvpsxq" ), + lightningState = LightningState( + nodeLifecycleState = NodeLifecycleState.Running, + channels = listOf(mockChannel), + ), onClickEditInvoice = {}, modifier = Modifier.sheetHeight(), initialTab = ReceiveTab.SPENDING, @@ -793,7 +801,8 @@ private fun PreviewNodeNotReady() { BottomSheetPreview { ReceiveQrScreen( cjitInvoice = null, - walletState = MainUiState( + walletState = WalletState(), + lightningState = LightningState( nodeLifecycleState = NodeLifecycleState.Starting, ), onClickReceiveCjit = {}, @@ -811,7 +820,8 @@ private fun PreviewSmall() { BottomSheetPreview { ReceiveQrScreen( cjitInvoice = null, - walletState = MainUiState( + walletState = WalletState(), + lightningState = LightningState( nodeLifecycleState = NodeLifecycleState.Running, ), onClickEditInvoice = {}, @@ -835,7 +845,7 @@ private fun PreviewDetailsMode() { ) { ReceiveDetailsView( tab = ReceiveTab.AUTO, - walletState = MainUiState( + walletState = WalletState( onchainAddress = "bcrt1qfserxgtuesul4m9zva56wzk849yf9l8rk4qy0l", bolt11 = "lnbcrt500u1pn7umn7pp5x0s9lt9fwrff6rp70pz3guwnjgw97sjuv79...", ), diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt index 3cee808dc..187054cff 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt @@ -17,19 +17,19 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.rememberNavController import kotlinx.serialization.Serializable import to.bitkit.repositories.LightningState +import to.bitkit.repositories.WalletState import to.bitkit.ui.screens.wallets.send.AddTagScreen import to.bitkit.ui.shared.modifiers.sheetHeight import to.bitkit.ui.utils.NotificationUtils import to.bitkit.ui.utils.composableWithDefaultTransitions import to.bitkit.ui.walletViewModel import to.bitkit.viewmodels.AmountInputViewModel -import to.bitkit.viewmodels.MainUiState import to.bitkit.viewmodels.SettingsViewModel @Composable fun ReceiveSheet( navigateToExternalConnection: () -> Unit, - walletState: MainUiState, + walletState: WalletState, editInvoiceAmountViewModel: AmountInputViewModel = hiltViewModel(), settingsViewModel: SettingsViewModel = hiltViewModel(), ) { @@ -67,6 +67,7 @@ fun ReceiveSheet( ReceiveQrScreen( cjitInvoice = cjitInvoice.value, walletState = walletState, + lightningState = lightningState, onClickReceiveCjit = { if (lightningState.isGeoBlocked) { navController.navigate(ReceiveRoute.GeoBlock) diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt index 215902134..292aeaca3 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt @@ -60,7 +60,6 @@ import to.bitkit.ui.theme.Colors import to.bitkit.viewmodels.AmountInputUiState import to.bitkit.viewmodels.AmountInputViewModel import to.bitkit.viewmodels.LnurlParams -import to.bitkit.viewmodels.MainUiState import to.bitkit.viewmodels.SendEvent import to.bitkit.viewmodels.SendMethod import to.bitkit.viewmodels.SendUiState @@ -70,7 +69,7 @@ import to.bitkit.viewmodels.previewAmountInputViewModel @Composable fun SendAmountScreen( uiState: SendUiState, - walletUiState: MainUiState, + nodeLifecycleState: NodeLifecycleState, canGoBack: Boolean, onBack: () -> Unit, onEvent: (SendEvent) -> Unit, @@ -99,7 +98,7 @@ fun SendAmountScreen( } SendAmountContent( - walletUiState = walletUiState, + nodeLifecycleState = nodeLifecycleState, uiState = uiState, amountInputViewModel = amountInputViewModel, currencies = currencies, @@ -125,7 +124,7 @@ fun SendAmountScreen( @Suppress("ViewModelForwarding") @Composable fun SendAmountContent( - walletUiState: MainUiState, + nodeLifecycleState: NodeLifecycleState, uiState: SendUiState, amountInputViewModel: AmountInputViewModel, modifier: Modifier = Modifier, @@ -154,7 +153,7 @@ fun SendAmountContent( onBack = onBack, ) - when (walletUiState.nodeLifecycleState) { + when (nodeLifecycleState) { is NodeLifecycleState.Running -> { SendAmountNodeRunning( amountInputViewModel = amountInputViewModel, @@ -328,7 +327,7 @@ private fun PreviewLightningNoAmount() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, ), @@ -351,7 +350,7 @@ private fun PreviewUnified() { ) } SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, isUnified = true, @@ -371,7 +370,7 @@ private fun PreviewOnchain() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.ONCHAIN, ), @@ -389,7 +388,7 @@ private fun PreviewInitializing() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Initializing), + nodeLifecycleState = NodeLifecycleState.Initializing, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, ), @@ -406,7 +405,7 @@ private fun PreviewWithdraw() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, lnurl = LnurlParams.LnurlWithdraw( @@ -435,7 +434,7 @@ private fun PreviewLnurlPay() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, lnurl = LnurlParams.LnurlPay( @@ -465,7 +464,7 @@ private fun PreviewSmallScreen() { AppThemeSurface { BottomSheetPreview { SendAmountContent( - walletUiState = MainUiState(nodeLifecycleState = NodeLifecycleState.Running), + nodeLifecycleState = NodeLifecycleState.Running, uiState = SendUiState( payMethod = SendMethod.LIGHTNING, ), diff --git a/app/src/main/java/to/bitkit/ui/settings/BlocktankRegtestScreen.kt b/app/src/main/java/to/bitkit/ui/settings/BlocktankRegtestScreen.kt index 47778d650..c09d03807 100644 --- a/app/src/main/java/to/bitkit/ui/settings/BlocktankRegtestScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/BlocktankRegtestScreen.kt @@ -50,7 +50,7 @@ fun BlocktankRegtestScreen( val coroutineScope = rememberCoroutineScope() val wallet = walletViewModel ?: return val app = appViewModel ?: return - val uiState by wallet.uiState.collectAsStateWithLifecycle() + val walletState by wallet.walletState.collectAsStateWithLifecycle() ScreenColumn { AppTopBar( @@ -65,7 +65,7 @@ fun BlocktankRegtestScreen( .verticalScroll(rememberScrollState()) .imePadding() ) { - var depositAddress by remember { mutableStateOf(uiState.onchainAddress) } + var depositAddress by remember { mutableStateOf(walletState.onchainAddress) } var depositAmount by remember { mutableStateOf("100000") } var mineBlockCount by remember { mutableStateOf("1") } var paymentInvoice by remember { mutableStateOf("") } diff --git a/app/src/main/java/to/bitkit/ui/settings/lightning/ChannelDetailScreen.kt b/app/src/main/java/to/bitkit/ui/settings/lightning/ChannelDetailScreen.kt index 3081689de..e67caecf8 100644 --- a/app/src/main/java/to/bitkit/ui/settings/lightning/ChannelDetailScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/lightning/ChannelDetailScreen.kt @@ -97,8 +97,7 @@ fun ChannelDetailScreen( val paidOrders by viewModel.blocktankRepo.blocktankState.collectAsStateWithLifecycle() val isClosedChannel = uiState.closedChannels.any { it.details.channelId == channel.details.channelId } - val txDetails by viewModel.txDetails.collectAsStateWithLifecycle() - val walletState by wallet.uiState.collectAsStateWithLifecycle() + val lightningState by wallet.lightningState.collectAsStateWithLifecycle() // Fetch transaction details for funding transaction if available LaunchedEffect(channel.details.fundingTxo?.txid) { @@ -140,7 +139,7 @@ fun ChannelDetailScreen( val intent = Intent(Intent.ACTION_VIEW, url.toUri()) context.startActivity(intent) }, - onSupport = { order -> contactSupport(order, channel, walletState.nodeId, context) }, + onSupport = { order -> contactSupport(order, channel, lightningState.nodeId, context) }, onCloseConnection = { navController.navigate(Routes.CloseConnection) }, ) } diff --git a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt index c3fec1648..2998520c5 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/SendSheet.kt @@ -111,10 +111,10 @@ fun SendSheet( } composableWithDefaultTransitions { val uiState by appViewModel.sendUiState.collectAsStateWithLifecycle() - val walletUiState by walletViewModel.uiState.collectAsStateWithLifecycle() + val lightningState by walletViewModel.lightningState.collectAsStateWithLifecycle() SendAmountScreen( uiState = uiState, - walletUiState = walletUiState, + nodeLifecycleState = lightningState.nodeLifecycleState, canGoBack = startDestination != SendRoute.Amount, onBack = { if (!navController.popBackStack()) { @@ -167,12 +167,12 @@ fun SendSheet( } composableWithDefaultTransitions { val uiState by appViewModel.sendUiState.collectAsStateWithLifecycle() - val walletUiState by walletViewModel.uiState.collectAsStateWithLifecycle() + val lightningState by walletViewModel.lightningState.collectAsStateWithLifecycle() SendConfirmScreen( savedStateHandle = it.savedStateHandle, uiState = uiState, - isNodeRunning = walletUiState.nodeLifecycleState.isRunning(), + isNodeRunning = lightningState.nodeLifecycleState.isRunning(), canGoBack = startDestination != SendRoute.Confirm, onBack = { if (!navController.popBackStack()) { diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index ecb6a37f3..acef6032b 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -60,8 +60,8 @@ import to.bitkit.data.resetPin import to.bitkit.di.BgDispatcher import to.bitkit.domain.commands.NotifyPaymentReceived import to.bitkit.domain.commands.NotifyPaymentReceivedHandler -import to.bitkit.env.Env import to.bitkit.env.Defaults +import to.bitkit.env.Env import to.bitkit.ext.WatchResult import to.bitkit.ext.amountOnClose import to.bitkit.ext.getClipboardText diff --git a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt index 7895faf4b..102c0fc39 100644 --- a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt @@ -16,16 +16,10 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withTimeoutOrNull -import org.lightningdevkit.ldknode.ChannelDataMigration -import org.lightningdevkit.ldknode.ChannelDetails -import org.lightningdevkit.ldknode.NodeStatus import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.data.SettingsStore import to.bitkit.di.BgDispatcher -import to.bitkit.models.NodeLifecycleState import to.bitkit.models.Toast import to.bitkit.repositories.BackupRepo import to.bitkit.repositories.BlocktankRepo @@ -79,10 +73,8 @@ class WalletViewModel @Inject constructor( private val _restoreState = MutableStateFlow(RestoreState.Initial) val restoreState: StateFlow = _restoreState.asStateFlow() - private val _uiState = MutableStateFlow(MainUiState()) - - @Deprecated("Prioritize get the wallet and lightning states from LightningRepo or WalletRepo") - val uiState = _uiState.asStateFlow() + private val _isRefreshing = MutableStateFlow(false) + val isRefreshing = _isRefreshing.asStateFlow() private var syncJob: Job? = null @@ -150,35 +142,11 @@ class WalletViewModel @Inject constructor( viewModelScope.launch { walletState.collect { state -> walletExists = state.walletExists - _uiState.update { - it.copy( - onchainAddress = state.onchainAddress, - bolt11 = state.bolt11, - bip21 = state.bip21, - bip21AmountSats = state.bip21AmountSats, - bip21Description = state.bip21Description, - selectedTags = state.selectedTags, - ) - } if (state.walletExists && _restoreState.value == RestoreState.InProgress.Wallet) { restoreFromBackup() } } } - - viewModelScope.launch { - lightningState.collect { state -> - _uiState.update { - it.copy( - nodeId = state.nodeId, - nodeStatus = state.nodeStatus, - nodeLifecycleState = state.nodeLifecycleState, - peers = state.peers, - channels = state.channels, - ) - } - } - } } private suspend fun restoreFromBackup() { @@ -319,11 +287,11 @@ class WalletViewModel @Inject constructor( lightningRepo.clearPendingSync() syncJob = viewModelScope.launch { - _uiState.update { it.copy(isRefreshing = true) } + _isRefreshing.value = true try { walletRepo.syncNodeAndWallet(source = SyncSource.MANUAL) } finally { - _uiState.update { it.copy(isRefreshing = false) } + _isRefreshing.value = false } } } @@ -432,22 +400,6 @@ class WalletViewModel @Inject constructor( } } -// TODO rename to walletUiState -data class MainUiState( - val nodeId: String = "", - val onchainAddress: String = "", - val bolt11: String = "", - val bip21: String = "", - val nodeStatus: NodeStatus? = null, - val nodeLifecycleState: NodeLifecycleState = NodeLifecycleState.Stopped, - val peers: List = emptyList(), - val channels: List = emptyList(), - val isRefreshing: Boolean = false, - val bip21AmountSats: ULong? = null, - val bip21Description: String = "", - val selectedTags: List = listOf(), -) - sealed interface RestoreState { data object Initial : RestoreState sealed interface InProgress : RestoreState { From 0d3f3a5f73ce5f32d8608d01c11b4a0b68042039 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 05:23:33 +0100 Subject: [PATCH 10/19] feat: localize remaining hardcoded strings --- .../main/java/to/bitkit/fcm/WakeNodeWorker.kt | 4 +- .../main/java/to/bitkit/ui/MainActivity.kt | 6 +- .../ui/components/NotificationPreview.kt | 6 +- .../ui/screens/profile/CreateProfileScreen.kt | 2 +- .../screens/transfer/SpendingConfirmScreen.kt | 18 ++- .../transfer/components/ProgressSteps.kt | 2 + .../external/ExternalConfirmScreen.kt | 6 +- .../ui/screens/wallets/SavingsWalletScreen.kt | 2 +- .../screens/wallets/SpendingWalletScreen.kt | 2 +- .../wallets/activity/ActivityDetailScreen.kt | 6 +- .../activity/DateRangeSelectorSheet.kt | 4 +- .../activity/components/ActivityRow.kt | 13 +- .../wallets/receive/ReceiveLiquidityScreen.kt | 4 +- .../wallets/withdraw/WithdrawErrorScreen.kt | 3 +- .../ui/settings/BackupSettingsScreen.kt | 2 +- .../ui/settings/LanguageSettingsScreen.kt | 4 +- .../advanced/CoinSelectPreferenceScreen.kt | 8 +- .../BackgroundPaymentsIntroScreen.kt | 8 +- .../BackgroundPaymentsSettings.kt | 54 ++++---- .../settings/general/GeneralSettingsScreen.kt | 8 +- .../ui/sheets/BackgroundPaymentsIntroSheet.kt | 6 +- .../bitkit/ui/sheets/BoostTransactionSheet.kt | 4 +- .../to/bitkit/ui/sheets/LnurlAuthSheet.kt | 9 +- .../to/bitkit/ui/utils/NotificationUtils.kt | 18 ++- .../java/to/bitkit/viewmodels/AppViewModel.kt | 18 +-- .../to/bitkit/viewmodels/WalletViewModel.kt | 16 ++- app/src/main/res/values/strings.xml | 52 +++++++- docs/strings.md | 118 ++++++++++++++++++ 28 files changed, 275 insertions(+), 128 deletions(-) create mode 100644 docs/strings.md diff --git a/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt b/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt index 77aedd670..93957ea27 100644 --- a/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt +++ b/app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt @@ -96,7 +96,7 @@ class WakeNodeWorker @AssistedInject constructor( Logger.error("Failed to open channel", e, context = TAG) bestAttemptContent = NotificationDetails( title = appContext.getString(R.string.notification_channel_open_failed_title), - body = e.message ?: appContext.getString(R.string.notification_unknown_error), + body = e.message ?: appContext.getString(R.string.common__error_desc), ) deliver() } @@ -106,7 +106,7 @@ class WakeNodeWorker @AssistedInject constructor( withTimeout(timeout) { deliverSignal.await() } // Stops node on timeout & avoids notification replay by OS return Result.success() } catch (e: Exception) { - val reason = e.message ?: appContext.getString(R.string.notification_unknown_error) + val reason = e.message ?: appContext.getString(R.string.common__error_desc) bestAttemptContent = NotificationDetails( title = appContext.getString(R.string.notification_lightning_error_title), diff --git a/app/src/main/java/to/bitkit/ui/MainActivity.kt b/app/src/main/java/to/bitkit/ui/MainActivity.kt index 4977eedd8..6faf85798 100644 --- a/app/src/main/java/to/bitkit/ui/MainActivity.kt +++ b/app/src/main/java/to/bitkit/ui/MainActivity.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlinx.serialization.Serializable +import to.bitkit.R import to.bitkit.androidServices.LightningNodeService import to.bitkit.androidServices.LightningNodeService.Companion.CHANNEL_ID_NODE import to.bitkit.models.NewTransactionSheetDetails @@ -77,10 +78,9 @@ class MainActivity : FragmentActivity() { initNotificationChannel() initNotificationChannel( - // TODO Transifex id = CHANNEL_ID_NODE, - name = "Lightning node notification", - desc = "Channel for LightningNodeService", + name = getString(R.string.notification_channel_node_name), + desc = getString(R.string.notification_channel_node_desc), importance = NotificationManager.IMPORTANCE_LOW ) appViewModel.handleDeeplinkIntent(intent) diff --git a/app/src/main/java/to/bitkit/ui/components/NotificationPreview.kt b/app/src/main/java/to/bitkit/ui/components/NotificationPreview.kt index f36ac8bce..ab850572f 100644 --- a/app/src/main/java/to/bitkit/ui/components/NotificationPreview.kt +++ b/app/src/main/java/to/bitkit/ui/components/NotificationPreview.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import to.bitkit.R @@ -50,7 +51,10 @@ fun NotificationPreview( verticalArrangement = Arrangement.SpaceBetween ) { BodySSB(text = title, color = Colors.Black) - val textDescription = if (showDetails) description else "Open Bitkit to see details" // TODO Transifex + val textDescription = when (showDetails) { + true -> description + else -> stringResource(R.string.notification_received_body_hidden) + } AnimatedContent(targetState = textDescription) { text -> Footnote(text = text, color = Colors.Gray3) } diff --git a/app/src/main/java/to/bitkit/ui/screens/profile/CreateProfileScreen.kt b/app/src/main/java/to/bitkit/ui/screens/profile/CreateProfileScreen.kt index 0c5071c03..8d8e11c83 100644 --- a/app/src/main/java/to/bitkit/ui/screens/profile/CreateProfileScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/profile/CreateProfileScreen.kt @@ -33,7 +33,7 @@ fun CreateProfileScreen( Spacer(Modifier.weight(1f)) Display( - text = "Comming soon", + text = stringResource(R.string.other__coming_soon), color = Colors.White ) Spacer(Modifier.weight(1f)) diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt index dd2c4cc60..3f62f2312 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -99,14 +100,12 @@ fun SpendingConfirmScreen( onLearnMoreClick = onLearnMoreClick, onAdvancedClick = onAdvancedClick, onConfirm = onConfirm, - onUseDefaultLspBalanceClick = { viewModel.onUseDefaultLspBalanceClick() }, - onTransferToSpendingConfirm = { order -> viewModel.onTransferToSpendingConfirm(order) }, + onUseDefaultLspBalanceClick = viewModel::onUseDefaultLspBalanceClick, + onTransferToSpendingConfirm = viewModel::onTransferToSpendingConfirm, order = order, hasNotificationPermission = notificationsGranted, - onSwitchClick = { - NotificationUtils.openNotificationSettings(context) - }, - isAdvanced = isAdvanced + onSwitchClick = { NotificationUtils.openNotificationSettings(context) }, + isAdvanced = isAdvanced, ) } @@ -140,7 +139,7 @@ private fun Content( modifier = Modifier .fillMaxWidth() .padding(horizontal = 60.dp) - .align(alignment = Alignment.BottomCenter) + .align(Alignment.BottomCenter) .padding(bottom = 76.dp) ) } @@ -158,10 +157,7 @@ private fun Content( val lspBalance = order.lspBalanceSat VerticalSpacer(32.dp) - Display( - text = stringResource(R.string.lightning__transfer__confirm) - .withAccent(accentColor = Colors.Purple) - ) + Display(stringResource(R.string.lightning__transfer__confirm).withAccent(accentColor = Colors.Purple)) VerticalSpacer(8.dp) Row( diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/components/ProgressSteps.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/components/ProgressSteps.kt index b3c53885d..987e755df 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/components/ProgressSteps.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/components/ProgressSteps.kt @@ -24,8 +24,10 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathEffect +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import to.bitkit.R import to.bitkit.ui.components.BodySSB import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt index fbaae5a19..9fd0426b5 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/external/ExternalConfirmScreen.kt @@ -66,7 +66,7 @@ fun ExternalConfirmScreen( Content( uiState = uiState, - onConfirm = { viewModel.onConfirm() }, + onConfirm = viewModel::onConfirm, onNetworkFeeClick = onNetworkFeeClick, onBackClick = onBackClick, ) @@ -96,9 +96,7 @@ private fun Content( val totalFee = uiState.amount.sats + networkFee Spacer(modifier = Modifier.height(16.dp)) - Display( - text = stringResource(R.string.lightning__transfer__confirm).withAccent(accentColor = Colors.Purple) - ) + Display(stringResource(R.string.lightning__transfer__confirm).withAccent(accentColor = Colors.Purple)) Spacer(modifier = Modifier.height(8.dp)) Row( diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt index cb3399fa2..7b2b48671 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SavingsWalletScreen.kt @@ -112,7 +112,7 @@ fun SavingsWalletScreen( if (canTransfer) { SecondaryButton( onClick = onTransferToSpendingClick, - text = "Transfer To Spending", // TODO add missing localized text + text = stringResource(R.string.wallet__transfer_to_spending), icon = { Icon( painter = painterResource(R.drawable.ic_transfer), diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt index 5d659ce1b..5aeac50d9 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletScreen.kt @@ -114,7 +114,7 @@ fun SpendingWalletScreen( if (canTransfer) { SecondaryButton( onClick = onTransferToSavingsClick, - text = "Transfer To Savings", // TODO add missing localized text + text = stringResource(R.string.wallet__transfer_to_savings), icon = { Icon( painter = painterResource(R.drawable.ic_transfer), diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt index 0e2a543f7..63886cd13 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt @@ -436,7 +436,7 @@ private fun ActivityDetailContent( text = when { isTransferToSpending -> stringResource(R.string.wallet__activity_transfer_to_spending) isTransferFromSpending -> stringResource(R.string.wallet__activity_transfer_to_savings) - isSelfSend -> "Sent to myself" // TODO add missing localized text + isSelfSend -> stringResource(R.string.wallet__activity_sent_self) else -> stringResource(R.string.wallet__activity_payment) }, color = Colors.White64, @@ -740,7 +740,6 @@ private fun StatusSection( if (item.v1.isTransfer) { val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) - .removeEstimationSymbol() statusText = stringResource(R.string.wallet__activity_transfer_pending) .replace("{duration}", duration) statusTestTag = "StatusTransfer" @@ -953,6 +952,3 @@ private fun isBoostCompleted( return activity.boostTxIds.any { boostTxDoesExist[it] == true } } } - -// TODO remove this method after transifex update -private fun String.removeEstimationSymbol() = this.replace("±", "") diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/DateRangeSelectorSheet.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/DateRangeSelectorSheet.kt index 6c47947fa..07580448a 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/DateRangeSelectorSheet.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/DateRangeSelectorSheet.kt @@ -255,7 +255,7 @@ private fun Content( ) { Icon( imageVector = Icons.AutoMirrored.Filled.KeyboardArrowLeft, - contentDescription = "Previous month", + contentDescription = stringResource(R.string.wallet__activity_previous_month), tint = Colors.Brand ) } @@ -268,7 +268,7 @@ private fun Content( ) { Icon( imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, - contentDescription = "Next month", + contentDescription = stringResource(R.string.wallet__activity_next_month), tint = Colors.Brand ) } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt index b7c9d7638..81962392a 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt @@ -130,7 +130,7 @@ fun ActivityRow( } else { val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) stringResource(R.string.wallet__activity_transfer_spending_pending) - .replace("{duration}", duration.removeEstimationSymbol()) + .replace("{duration}", duration) } isTransfer && !isSent -> if (item.v1.confirmed) { @@ -138,17 +138,15 @@ fun ActivityRow( } else { val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) stringResource(R.string.wallet__activity_transfer_savings_pending) - .replace("{duration}", duration.removeEstimationSymbol()) + .replace("{duration}", duration) } confirmed == true -> formattedTime(timestamp) else -> { val feeDescription = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) - stringResource(R.string.wallet__activity_confirms_in).replace( - "{feeRateDescription}", - feeDescription - ) + stringResource(R.string.wallet__activity_confirms_in) + .replace("{feeRateDescription}", feeDescription) } } } @@ -323,9 +321,6 @@ private fun formattedTime(timestamp: ULong): String { } } -// TODO remove this method after transifex update -private fun String.removeEstimationSymbol() = this.replace("±", "") - private class ActivityItemsPreviewProvider : PreviewParameterProvider { override val values: Sequence get() = previewActivityItems.asSequence() } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveLiquidityScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveLiquidityScreen.kt index 5f3b9c801..4cfc6b879 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveLiquidityScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveLiquidityScreen.kt @@ -131,14 +131,14 @@ private fun Content( FillHeight() BodyM( - text = "Enable background setup to safely exit Bitkit while your balance is being configured.", + text = stringResource(R.string.wallet__receive_liquidity__bg_setup_desc), color = Colors.White64 ) VerticalSpacer(15.dp) SettingsSwitchRow( - title = "Set up in background", + title = stringResource(R.string.wallet__receive_liquidity__bg_setup_switch), isChecked = hasNotificationPermission, colors = AppSwitchDefaults.colorsPurple, onClick = onSwitchClick, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/withdraw/WithdrawErrorScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/withdraw/WithdrawErrorScreen.kt index bae5d34bf..f2f7b6f65 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/withdraw/WithdrawErrorScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/withdraw/WithdrawErrorScreen.kt @@ -56,8 +56,7 @@ fun WithdrawErrorScreen( VerticalSpacer(46.dp) BodyM( - // TODO add missing localized text - text = "Your withdrawal was unsuccessful. Please scan the QR code again or contact support.", + text = stringResource(R.string.wallet__withdraw_error), color = Colors.White64, ) diff --git a/app/src/main/java/to/bitkit/ui/settings/BackupSettingsScreen.kt b/app/src/main/java/to/bitkit/ui/settings/BackupSettingsScreen.kt index 558d127f2..903b61124 100644 --- a/app/src/main/java/to/bitkit/ui/settings/BackupSettingsScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/BackupSettingsScreen.kt @@ -124,7 +124,7 @@ private fun BackupSettingsScreenContent( if (Env.isE2eTest && allSynced) { Icon( painter = painterResource(R.drawable.ic_check_circle), - contentDescription = "All Synced", + contentDescription = null, tint = Colors.Green, modifier = Modifier .padding(end = 4.dp) diff --git a/app/src/main/java/to/bitkit/ui/settings/LanguageSettingsScreen.kt b/app/src/main/java/to/bitkit/ui/settings/LanguageSettingsScreen.kt index 3b21f3a2d..9c0276207 100644 --- a/app/src/main/java/to/bitkit/ui/settings/LanguageSettingsScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/LanguageSettingsScreen.kt @@ -8,10 +8,12 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import to.bitkit.R import to.bitkit.models.Language import to.bitkit.ui.components.Text13Up import to.bitkit.ui.components.settings.SettingsButtonRow @@ -53,7 +55,7 @@ private fun Content( modifier = modifier.screen() ) { AppTopBar( - titleText = "Language", // TODO Transifex + titleText = stringResource(R.string.settings__language_title), onBackClick = onBackClick, actions = { DrawerNavIcon() } ) diff --git a/app/src/main/java/to/bitkit/ui/settings/advanced/CoinSelectPreferenceScreen.kt b/app/src/main/java/to/bitkit/ui/settings/advanced/CoinSelectPreferenceScreen.kt index 9555246b5..dbe193a4c 100644 --- a/app/src/main/java/to/bitkit/ui/settings/advanced/CoinSelectPreferenceScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/advanced/CoinSelectPreferenceScreen.kt @@ -143,8 +143,8 @@ private fun Content( // ) SettingsButtonRow( - title = "Branch and Bound", // TODO add missing localized text - description = "Finds exact amount matches to minimize change", // TODO add missing localized text + title = stringResource(R.string.settings__cs__bnb_title), + description = stringResource(R.string.settings__cs__bnb_desc), value = SettingsButtonValue.BooleanValue( uiState.coinSelectionPreference == CoinSelectionPreference.BranchAndBound ), @@ -153,8 +153,8 @@ private fun Content( ) SettingsButtonRow( - title = "Single Random Draw", // TODO add missing localized text - description = "Random selection for privacy", // TODO add missing localized text + title = stringResource(R.string.settings__cs__srd_title), + description = stringResource(R.string.settings__cs__srd_desc), value = SettingsButtonValue.BooleanValue( uiState.coinSelectionPreference == CoinSelectionPreference.SingleRandomDraw ), diff --git a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsIntroScreen.kt b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsIntroScreen.kt index 08204ea77..73c8a8457 100644 --- a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsIntroScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsIntroScreen.kt @@ -36,7 +36,7 @@ fun BackgroundPaymentsIntroScreen( modifier = modifier.screen() ) { AppTopBar( - titleText = "Background Payments", // Todo Transifex + titleText = stringResource(R.string.settings__bg__title), onBackClick = onBack, actions = { DrawerNavIcon() }, ) @@ -66,11 +66,11 @@ fun BackgroundPaymentsIntroContent( ) Display( - text = "GET PAID\nPASSIVELY".withAccent(accentColor = Colors.Blue), - color = Colors.White + text = stringResource(R.string.settings__bg__intro_title).withAccent(accentColor = Colors.Blue), + color = Colors.White, ) VerticalSpacer(8.dp) - BodyM(text = "Turn on notifications to get paid, even when your Bitkit app is closed.", color = Colors.White64) + BodyM(text = stringResource(R.string.settings__bg__intro_desc), color = Colors.White64) VerticalSpacer(32.dp) PrimaryButton( text = stringResource(R.string.common__continue), diff --git a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt index 562bbfe62..c1021acf8 100644 --- a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt +++ b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel @@ -35,44 +36,40 @@ import to.bitkit.viewmodels.SettingsViewModel @Composable fun BackgroundPaymentsSettings( - onBack: () -> Unit, settingsViewModel: SettingsViewModel = hiltViewModel(), + onBack: () -> Unit, ) { val context = LocalContext.current val notificationsGranted by settingsViewModel.notificationsGranted.collectAsStateWithLifecycle() val showNotificationDetails by settingsViewModel.showNotificationDetails.collectAsStateWithLifecycle() RequestNotificationPermissions( - onPermissionChange = { granted -> - settingsViewModel.setNotificationPreference(granted) - }, - showPermissionDialog = false + onPermissionChange = settingsViewModel::setNotificationPreference, + showPermissionDialog = false, ) Content( - onBack = onBack, - onSystemSettingsClick = { - NotificationUtils.openNotificationSettings(context) - }, hasPermission = notificationsGranted, showDetails = showNotificationDetails, + onBack = onBack, + onSystemSettingsClick = { NotificationUtils.openNotificationSettings(context) }, toggleNotificationDetails = settingsViewModel::toggleNotificationDetails, ) } @Composable private fun Content( + hasPermission: Boolean, + showDetails: Boolean, onBack: () -> Unit, onSystemSettingsClick: () -> Unit, toggleNotificationDetails: () -> Unit, - hasPermission: Boolean, - showDetails: Boolean, ) { Column( modifier = Modifier.screen() ) { AppTopBar( - titleText = "Background Payments", + titleText = stringResource(R.string.settings__bg__title), onBackClick = onBack, actions = { DrawerNavIcon() }, ) @@ -85,15 +82,14 @@ private fun Content( VerticalSpacer(16.dp) SettingsSwitchRow( - title = "Get paid when Bitkit is closed", + title = stringResource(R.string.settings__bg__switch_title), isChecked = hasPermission, - onClick = onSystemSettingsClick + onClick = onSystemSettingsClick, ) if (hasPermission) { - @Suppress("MaxLineLength") // TODO transifex BodyM( - text = "Background payments are enabled. You can receive funds even when the app is closed (if your device is connected to the internet).", + text = stringResource(R.string.settings__bg__enabled), color = Colors.White64, modifier = Modifier.padding(vertical = 16.dp), ) @@ -104,14 +100,14 @@ private fun Content( modifier = Modifier.padding(vertical = 16.dp) ) { BodyMB( - text = "Background payments are disabled, because you have denied notifications.", + text = stringResource(R.string.settings__bg__disabled), color = Colors.Red, ) } NotificationPreview( enabled = hasPermission, - title = "Payment Received", + title = stringResource(R.string.notification_received_title), description = "₿ 21 000", showDetails = showDetails, modifier = Modifier.fillMaxWidth() @@ -120,12 +116,12 @@ private fun Content( VerticalSpacer(32.dp) Text13Up( - text = "Privacy", + text = stringResource(R.string.settings__bg__privacy_header), color = Colors.White64 ) SettingsButtonRow( - "Include amount in notifications", + stringResource(R.string.settings__bg__include_amount), value = SettingsButtonValue.BooleanValue(showDetails), onClick = toggleNotificationDetails, ) @@ -133,18 +129,16 @@ private fun Content( VerticalSpacer(32.dp) Text13Up( - text = "Notifications", + text = stringResource(R.string.settings__bg__notifications_header), color = Colors.White64 ) VerticalSpacer(16.dp) SecondaryButton( - "Customize in Android Bitkit Settings", - icon = { - Image(painter = painterResource(R.drawable.ic_bell), contentDescription = null) - }, - onClick = onSystemSettingsClick + stringResource(R.string.settings__bg__customize), + icon = { Image(painter = painterResource(R.drawable.ic_bell), contentDescription = null) }, + onClick = onSystemSettingsClick, ) } } @@ -155,11 +149,11 @@ private fun Content( private fun Preview1() { AppThemeSurface { Content( + hasPermission = true, + showDetails = true, onBack = {}, onSystemSettingsClick = {}, toggleNotificationDetails = {}, - hasPermission = true, - showDetails = true, ) } } @@ -169,11 +163,11 @@ private fun Preview1() { private fun Preview2() { AppThemeSurface { Content( + hasPermission = false, + showDetails = false, onBack = {}, onSystemSettingsClick = {}, toggleNotificationDetails = {}, - hasPermission = false, - showDetails = false, ) } } diff --git a/app/src/main/java/to/bitkit/ui/settings/general/GeneralSettingsScreen.kt b/app/src/main/java/to/bitkit/ui/settings/general/GeneralSettingsScreen.kt index cc63bfc56..1e188b51c 100644 --- a/app/src/main/java/to/bitkit/ui/settings/general/GeneralSettingsScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/general/GeneralSettingsScreen.kt @@ -109,7 +109,7 @@ private fun GeneralSettingsContent( .verticalScroll(rememberScrollState()) ) { SettingsButtonRow( - title = "Language", + title = stringResource(R.string.settings__language_title), value = SettingsButtonValue.StringValue(selectedLanguage), onClick = onLanguageSettingsClick, modifier = Modifier.testTag("LanguageSettings") @@ -155,9 +155,11 @@ private fun GeneralSettingsContent( modifier = Modifier.testTag("QuickpaySettings") ) SettingsButtonRow( - title = "Background Payments", // TODO Transifex + title = stringResource(R.string.settings__bg__title), onClick = onBgPaymentsClick, - value = SettingsButtonValue.StringValue(if (notificationsGranted) "On" else "Off"), + value = SettingsButtonValue.StringValue( + stringResource(if (notificationsGranted) R.string.settings__bg__on else R.string.settings__bg__off) + ), modifier = Modifier.testTag("BackgroundPaymentSettings") ) } diff --git a/app/src/main/java/to/bitkit/ui/sheets/BackgroundPaymentsIntroSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/BackgroundPaymentsIntroSheet.kt index feae729ea..7daaf880d 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/BackgroundPaymentsIntroSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/BackgroundPaymentsIntroSheet.kt @@ -6,7 +6,9 @@ import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import to.bitkit.R import to.bitkit.ui.components.BottomSheetPreview import to.bitkit.ui.scaffold.SheetTopBar import to.bitkit.ui.settings.backgroundPayments.BackgroundPaymentsIntroContent @@ -27,9 +29,7 @@ fun BackgroundPaymentsIntroSheet( .navigationBarsPadding() .testTag("background_payments_intro_sheet") ) { - SheetTopBar( - titleText = "Background Payments", // Todo Transifex - ) + SheetTopBar(titleText = stringResource(R.string.settings__bg__title)) BackgroundPaymentsIntroContent(onContinue = onContinue) } } diff --git a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionSheet.kt index f9d38456a..2ba8313cb 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionSheet.kt @@ -302,7 +302,7 @@ private fun CustomModeContent( backgroundColor = Colors.Red16, enabled = uiState.decreaseEnabled, onClick = { onChangeAmount(false) }, - contentDescription = "Reduce fee", + contentDescription = stringResource(R.string.wallet__boost_decrease_fee), modifier = Modifier.testTag(BoostTransactionTestTags.DECREASE_FEE_BUTTON) ) @@ -349,7 +349,7 @@ private fun CustomModeContent( backgroundColor = Colors.Green16, enabled = uiState.increaseEnabled, onClick = { onChangeAmount(true) }, - contentDescription = "Increase fee", + contentDescription = stringResource(R.string.wallet__boost_increase_fee), modifier = Modifier.testTag(BoostTransactionTestTags.INCREASE_FEE_BUTTON) ) } diff --git a/app/src/main/java/to/bitkit/ui/sheets/LnurlAuthSheet.kt b/app/src/main/java/to/bitkit/ui/sheets/LnurlAuthSheet.kt index 36c951e96..711b13ebd 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/LnurlAuthSheet.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/LnurlAuthSheet.kt @@ -62,13 +62,11 @@ private fun Content( .navigationBarsPadding() .padding(horizontal = 16.dp) ) { - // TODO add missing localized text - SheetTopBar(titleText = "Log In") + SheetTopBar(titleText = stringResource(R.string.other__lnurl_auth_login_title)) VerticalSpacer(16.dp) BodyM( - // TODO add missing localized text - text = "Log in to {domain}?".replace("{domain}", domain), + text = stringResource(R.string.other__lnurl_auth_login_prompt).replace("{domain}", domain), color = Colors.White64, ) @@ -93,9 +91,8 @@ private fun Content( .weight(1f) .testTag("LnurlAuthCancel") ) - // TODO add missing localized text PrimaryButton( - text = "Log In", + text = stringResource(R.string.other__lnurl_auth_login_button), onClick = onContinue, fullWidth = false, modifier = Modifier diff --git a/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt b/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt index 61445ae23..e74efc74e 100644 --- a/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt +++ b/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt @@ -1,6 +1,6 @@ package to.bitkit.ui.utils -import android.Manifest +import android.Manifest.permission.POST_NOTIFICATIONS import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -17,17 +17,16 @@ object NotificationUtils { * On older versions, opens the general app settings. */ fun openNotificationSettings(context: Context) { - val intent = - Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { - putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) - } + val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) + } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) runCatching { context.startActivity(intent) - }.onFailure { e -> - Logger.error("Failed to open notification settings", e = e, context = "NotificationUtils") + }.onFailure { + Logger.error("Failed to open notification settings", e = it, context = "NotificationUtils") } } @@ -38,10 +37,7 @@ object NotificationUtils { */ fun areNotificationsEnabled(context: Context): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - ContextCompat.checkSelfPermission( - context, - Manifest.permission.POST_NOTIFICATIONS - ) == PackageManager.PERMISSION_GRANTED + ContextCompat.checkSelfPermission(context, POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED } else { NotificationManagerCompat.from(context).areNotificationsEnabled() } diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index acef6032b..b8277fa03 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -971,8 +971,8 @@ class AppViewModel @Inject constructor( if (!lightningRepo.canSend(invoice.amountSatoshis)) { toast( type = Toast.ToastType.ERROR, - title = "Insufficient Funds", - description = "You do not have enough funds to send this payment." + title = context.getString(R.string.wallet__error_insufficient_funds_title), + description = context.getString(R.string.wallet__error_insufficient_funds_msg) ) return } @@ -1317,7 +1317,7 @@ class AppViewModel @Inject constructor( it.copy(decodedInvoice = invoice) } }.onFailure { - toast(Exception("Error fetching lnurl invoice")) + toast(Exception(context.getString(R.string.wallet__error_lnurl_invoice_fetch))) hideSheet() return } @@ -1330,7 +1330,7 @@ class AppViewModel @Inject constructor( val validatedAddress = runCatching { validateBitcoinAddress(address) } .getOrElse { e -> Logger.error("Invalid bitcoin send address: '$address'", e, context = TAG) - toast(Exception("Invalid bitcoin send address")) + toast(Exception(context.getString(R.string.wallet__error_invalid_bitcoin_address))) hideSheet() return } @@ -1354,8 +1354,8 @@ class AppViewModel @Inject constructor( Logger.error(msg = "Error sending onchain payment", e = e, context = TAG) toast( type = Toast.ToastType.ERROR, - title = "Error Sending", - description = e.message ?: "Unknown error" + title = context.getString(R.string.wallet__error_sending_title), + description = e.message ?: context.getString(R.string.common__error_desc) ) hideSheet() } @@ -1808,7 +1808,11 @@ class AppViewModel @Inject constructor( } fun toast(error: Throwable) { - toast(type = Toast.ToastType.ERROR, title = "Error", description = error.message ?: "Unknown error") + toast( + type = Toast.ToastType.ERROR, + title = context.getString(R.string.common__error), + description = error.message ?: context.getString(R.string.common__error_desc) + ) } fun toast(toast: Toast) { diff --git a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt index 102c0fc39..7e79459ec 100644 --- a/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/WalletViewModel.kt @@ -1,11 +1,13 @@ package to.bitkit.viewmodels +import android.content.Context import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Job import kotlinx.coroutines.async @@ -18,6 +20,7 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import org.lightningdevkit.ldknode.PeerDetails +import to.bitkit.R import to.bitkit.data.SettingsStore import to.bitkit.di.BgDispatcher import to.bitkit.models.Toast @@ -39,6 +42,7 @@ import kotlin.time.Duration.Companion.seconds @HiltViewModel class WalletViewModel @Inject constructor( + @ApplicationContext private val context: Context, @BgDispatcher private val bgDispatcher: CoroutineDispatcher, private val walletRepo: WalletRepo, private val lightningRepo: LightningRepo, @@ -302,15 +306,15 @@ class WalletViewModel @Inject constructor( .onSuccess { ToastEventBus.send( type = Toast.ToastType.INFO, - title = "Success", - description = "Peer disconnected." + title = context.getString(R.string.common__success), + description = "Peer disconnected.," ) } .onFailure { error -> ToastEventBus.send( type = Toast.ToastType.ERROR, - title = "Error", - description = error.message ?: "Unknown error" + title = context.getString(R.string.common__error), + description = error.message ?: context.getString(R.string.common__error_desc) ) } } @@ -323,8 +327,8 @@ class WalletViewModel @Inject constructor( walletRepo.updateBip21Invoice(amountSats).onFailure { error -> ToastEventBus.send( type = Toast.ToastType.ERROR, - title = "Error updating invoice", - description = error.message ?: "Unknown error" + title = context.getString(R.string.wallet__error_invoice_update), + description = error.message ?: context.getString(R.string.common__error_desc) ) } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 41729a2dc..6305c7dc5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -73,6 +73,9 @@ Max Default Preview + Error + Unknown error + Success Instant ±2-10 seconds 2-10s @@ -362,6 +365,7 @@ <bold>It appears Bitkit does not have permission to access your camera.</bold>\n\nTo utilize this feature in the future you will need to enable camera permissions for this app from your phone\'s settings. Clipboard Data Detected Do you want to be redirected to the relevant screen? + Coming soon Insufficient Savings Insufficient Spending Balance More ₿ needed to pay this Bitcoin invoice. @@ -390,6 +394,9 @@ Channel Requested Successfully requested channel from: {peer} Successfully requested channel. + Log In + Log in to {domain}? + Log In Sign In Failed (LNURL) An error occurred when you attempted to sign in. {raw} Signed In @@ -608,6 +615,23 @@ If enabled, scanned invoices below ${amount} will be paid automatically without requiring your confirmation or PIN*. Quickpay threshold * Bitkit QuickPay exclusively supports payments from your Spending Balance. + Background Payments + On + Off + Background payments are enabled. You can receive funds even when the app is closed (if your device is connected to the internet). + Background payments are disabled, because you have denied notifications. + GET PAID\n<accent>PASSIVELY</accent> + Turn on notifications to get paid, even when your Bitkit app is closed. + Customize in Android Bitkit Settings + Include amount in notifications + Notifications + Privacy + Get paid when Bitkit is closed + Branch and Bound + Finds exact amount matches to minimize change + Single Random Draw + Random selection for privacy + Language Security And Privacy Swipe balance to hide Hide balance on open @@ -853,8 +877,6 @@ Unable To Delete Profile Unable To Pay Contact The contact you’re trying to send to hasn’t enabled payments. - Deprecated - Slashauth is deprecated. Please use Bitkit Beta. Wallet Activity Contacts @@ -989,6 +1011,8 @@ Your Spending Balance uses the Lightning Network to make your payments cheaper, faster, and more private.\n\nThis works like internet access, but you pay for liquidity & routing instead of bandwidth.\n\nBitkit needs to increase the receiving capacity of your spending balance to process this payment. Spending Balance Liquidity Additional Spending Balance Liquidity + Enable background setup to safely exit Bitkit while your balance is being configured. + Set up in background Transaction Failed Failed to send funds to your spending account. You will receive @@ -1004,19 +1028,20 @@ No activity yet Receive some funds to get started Sent + Sent to myself Received Pending Failed Boost Fee Boosted incoming transaction Transfer - From Spending (±{duration}) + From Spending ({duration}) From Spending - From Savings (±{duration}) + From Savings ({duration}) From Savings To Spending To Savings - Transfer (±{duration}) + Transfer ({duration}) Confirms in {feeRateDescription} Boosting. Confirms in {feeRateDescription} Fee potentially too low @@ -1064,6 +1089,8 @@ Sent Received Other + Next month + Previous month Savings Spending Savings @@ -1071,6 +1098,8 @@ Spending <accent>Send\nbitcoin</accent>\nto your\nspending balance Incoming Transfer: + Transfer To Savings + Transfer To Spending Transaction Invalid Boost Boost Transaction @@ -1083,13 +1112,23 @@ Your transaction may settle faster if you include an additional network fee. Here is a recommendation: Use Suggested Fee Swipe To Boost + Reduce fee + Increase fee Received Bitcoin Received Instant Bitcoin + Peer disconnected. Transaction Creation Failed An error occurred. Please try again {raw} Transaction Broadcast Failed An error occurred when broadcasting your transaction. {raw} Please check your connection and try again.\n{message} + Insufficient Funds + You do not have enough funds to send this payment. + Invalid bitcoin send address + Error updating invoice + Error fetching lnurl invoice + Error Sending + Your withdrawal was unsuccessful. Please scan the QR code again or contact support. Select Range Clear Apply @@ -1162,6 +1201,8 @@ Channel opened Pending Ready to send + Lightning node notification + Channel for LightningNodeService Lightning error Payment failed Please try again @@ -1170,7 +1211,6 @@ Payment Received Bitkit is running in background so you can receive Lightning payments Stop App - Unknown error Via new channel Lightning Wallet Sync Time Ready diff --git a/docs/strings.md b/docs/strings.md new file mode 100644 index 000000000..f411b80f7 --- /dev/null +++ b/docs/strings.md @@ -0,0 +1,118 @@ +# Untranslated Strings Tracker + +This document tracks hardcoded strings in the codebase. Strings in dev-only screens do not need translation. + +## Dev-Only Strings (No Translation Needed) + +These screens are only accessible in development builds and contain hardcoded strings that don't need localization. + +### DevSettingsScreen.kt +| Line | String | +|------|--------| +| 52 | Fee Settings | +| 53 | Channel Orders | +| 54 | LDK Debug | +| 56 | LOGS | +| 57 | Logs | +| 59 | Export Logs | +| 66 | REGTEST | +| 68 | Blocktank Regtest | +| 71 | APP CACHE | +| 74 | Reset Settings State | +| 77 | Settings state reset | +| 81 | Reset All Activities | +| 84 | Activities removed | +| 88 | Reset Backup State | +| 91 | Backup state reset | +| 95 | Reset Widgets State | +| 98 | Widgets state reset | +| 102 | Refresh Currency Rates | +| 105 | Currency rates refreshed | +| 109 | Reset App Database | +| 112 | Database state reset | +| 116 | Reset Blocktank State | +| 119 | Blocktank state reset | +| 123 | Reset Cache Store | +| 126 | Cache store reset | +| 130 | Wipe App | +| 133 | Wallet wiped | +| 137 | DEBUG | +| 140 | Generate Test Activities | +| 144 | Generated $count test activities | +| 148 | Fake New BG Receive | +| 151 | Restart app to see the payment received sheet | +| 155 | Open Channel To Trusted Peer | +| 161 | NOTIFICATIONS | +| 164 | Register For LSP Notifications | +| 170 | Test LSP Notification | + +### LdkDebugScreen.kt +| Line | String | +|------|--------| +| 96 | LDK Debug | +| 105 | ADD PEER | +| 109 | pubkey@host:port | +| 120 | Add Peer | +| 127 | Paste & Add | +| 135 | NETWORK GRAPH | +| 137 | Log Graph Info | +| 149 | Export to File | +| 160 | VSS | +| 162 | List Keys | +| 164 | found | +| 191 | Delete key | +| 205 | Delete All | +| 211 | NODE | +| 213 | Restart | +| 225 | Delete All VSS Keys? | +| 226 | This will permanently delete all... | +| 227 | Delete All | + +### BlocktankRegtestScreen.kt +| Line | String | +|------|--------| +| 57 | Blocktank Regtest | +| 81 | These actions are executed on the staging Blocktank server node. | +| 84 | DEPOSIT | +| 97 | Amount (sats) | +| 104 | Depositing... / Make Deposit | +| 116 | Success | +| 117 | Deposit successful. TxID: ... | +| 123 | Failed to deposit | +| 136 | MINING | +| 146 | Block Count | +| 180 | Mining... / Mine Blocks | +| 162 | Success | +| 163 | Successfully mined $count blocks | +| 169 | Failed to mine | +| 185 | LIGHTNING PAYMENT | +| 189 | Invoice | +| 197 | Amount (optional, sats) | +| 204 | Pay Invoice | +| 215 | Success | +| 216 | Payment successful. ID: ... | +| 222 | Failed to pay invoice from LND | +| 232 | CHANNEL CLOSE | +| 236 | Funding TxID | +| 244 | Vout | +| 253 | Force Close After (seconds) | +| 260 | Close Channel | +| 279 | Success | +| 280 | Channel closed. Closing TxID: ... | + +### LogsScreen.kt +- All strings are technical log display (no localization needed) + +### ChannelOrdersScreen.kt +- All strings are technical channel order data (no localization needed) + +## Preview Functions + +Hardcoded strings in `@Preview` functions throughout the codebase do not need translation as they are only visible in Android Studio previews, not to end users. + +## Borderline Cases + +| File | Line | String | Notes | +|------|------|--------|-------| +| NotificationPreview.kt | 63 | 3m ago | Placeholder in notification mockup | +| BackgroundPaymentsSettings.kt | 111 | ₿ 21 000 | Example amount in preview | From 546710070b2c3f50e6f5411113d7a045bea24125 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 05:33:34 +0100 Subject: [PATCH 11/19] refactor: turn NotificationUtils fns to ext --- .../main/java/to/bitkit/ui/Notifications.kt | 23 +++++++++- .../screens/transfer/SpendingConfirmScreen.kt | 4 +- .../wallets/receive/ReceiveConfirmScreen.kt | 6 +-- .../screens/wallets/receive/ReceiveSheet.kt | 10 ++--- .../BackgroundPaymentsSettings.kt | 4 +- .../to/bitkit/ui/utils/NotificationUtils.kt | 45 ------------------- .../utils/RequestNotificationPermissions.kt | 7 +-- 7 files changed, 35 insertions(+), 64 deletions(-) delete mode 100644 app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt diff --git a/app/src/main/java/to/bitkit/ui/Notifications.kt b/app/src/main/java/to/bitkit/ui/Notifications.kt index 58b2ccbda..a41717f82 100644 --- a/app/src/main/java/to/bitkit/ui/Notifications.kt +++ b/app/src/main/java/to/bitkit/ui/Notifications.kt @@ -1,6 +1,7 @@ package to.bitkit.ui import android.Manifest +import android.Manifest.* import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent @@ -9,10 +10,14 @@ import android.app.PendingIntent.FLAG_ONE_SHOT import android.content.Context import android.content.Intent import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP +import android.content.pm.PackageManager import android.media.RingtoneManager import android.os.Build import android.os.Bundle +import android.provider.Settings import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import androidx.core.content.ContextCompat import to.bitkit.R import to.bitkit.ext.notificationManager import to.bitkit.ext.notificationManagerCompat @@ -66,7 +71,7 @@ internal fun Context.pushNotification( // Only check permission if running on Android 13+ (SDK 33+) val needsPermissionGrant = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && - requiresPermission(Manifest.permission.POST_NOTIFICATIONS) + requiresPermission(permission.POST_NOTIFICATIONS) if (!needsPermissionGrant) { val builder = notificationBuilder(extras) @@ -87,4 +92,20 @@ internal fun Context.pushNotification( } } +fun Context.openNotificationSettings() { + val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra(Settings.EXTRA_APP_PACKAGE, packageName) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + runCatching { startActivity(intent) } + .onFailure { Logger.error("Failed to open notification settings", e = it, context = TAG) } +} + +fun Context.areNotificationsEnabled(): Boolean = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + ContextCompat.checkSelfPermission(this, permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + NotificationManagerCompat.from(this).areNotificationsEnabled() + } + private const val TAG = "Notifications" diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt index 3f62f2312..86198aeca 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/SpendingConfirmScreen.kt @@ -57,10 +57,10 @@ import to.bitkit.ui.components.settings.SettingsSwitchRow import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.DrawerNavIcon import to.bitkit.ui.scaffold.ScreenColumn +import to.bitkit.ui.openNotificationSettings import to.bitkit.ui.theme.AppSwitchDefaults import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors -import to.bitkit.ui.utils.NotificationUtils import to.bitkit.ui.utils.RequestNotificationPermissions import to.bitkit.ui.utils.withAccent import to.bitkit.viewmodels.SettingsViewModel @@ -104,7 +104,7 @@ fun SpendingConfirmScreen( onTransferToSpendingConfirm = viewModel::onTransferToSpendingConfirm, order = order, hasNotificationPermission = notificationsGranted, - onSwitchClick = { NotificationUtils.openNotificationSettings(context) }, + onSwitchClick = { context.openNotificationSettings() }, isAdvanced = isAdvanced, ) } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveConfirmScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveConfirmScreen.kt index 611224d24..442133b71 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveConfirmScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveConfirmScreen.kt @@ -39,10 +39,10 @@ import to.bitkit.ui.currencyViewModel import to.bitkit.ui.scaffold.SheetTopBar import to.bitkit.ui.shared.modifiers.sheetHeight import to.bitkit.ui.shared.util.gradientBackground +import to.bitkit.ui.openNotificationSettings import to.bitkit.ui.theme.AppSwitchDefaults import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors -import to.bitkit.ui.utils.NotificationUtils import to.bitkit.ui.utils.withAccent import to.bitkit.viewmodels.SettingsViewModel @@ -107,9 +107,7 @@ fun ReceiveConfirmScreen( receiveAmountFormatted = receiveAmountFormatted, onLearnMoreClick = onLearnMore, isAdditional = isAdditional, - onSystemSettingsClick = { - NotificationUtils.openNotificationSettings(context) - }, + onSystemSettingsClick = { context.openNotificationSettings() }, hasNotificationPermission = notificationsGranted, onContinueClick = { onContinue(entry.invoice) }, onBackClick = onBack, diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt index 187054cff..d948c29e8 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/receive/ReceiveSheet.kt @@ -19,8 +19,8 @@ import kotlinx.serialization.Serializable import to.bitkit.repositories.LightningState import to.bitkit.repositories.WalletState import to.bitkit.ui.screens.wallets.send.AddTagScreen +import to.bitkit.ui.openNotificationSettings import to.bitkit.ui.shared.modifiers.sheetHeight -import to.bitkit.ui.utils.NotificationUtils import to.bitkit.ui.utils.composableWithDefaultTransitions import to.bitkit.ui.walletViewModel import to.bitkit.viewmodels.AmountInputViewModel @@ -131,9 +131,7 @@ fun ReceiveSheet( onContinue = { navController.popBackStack() }, onBack = { navController.popBackStack() }, hasNotificationPermission = notificationsGranted, - onSwitchClick = { - NotificationUtils.openNotificationSettings(context) - }, + onSwitchClick = { context.openNotificationSettings() }, ) } } @@ -148,9 +146,7 @@ fun ReceiveSheet( isAdditional = true, onBack = { navController.popBackStack() }, hasNotificationPermission = notificationsGranted, - onSwitchClick = { - NotificationUtils.openNotificationSettings(context) - }, + onSwitchClick = { context.openNotificationSettings() }, ) } } diff --git a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt index c1021acf8..bb26bad83 100644 --- a/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt +++ b/app/src/main/java/to/bitkit/ui/settings/backgroundPayments/BackgroundPaymentsSettings.kt @@ -28,9 +28,9 @@ import to.bitkit.ui.components.settings.SettingsSwitchRow import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.DrawerNavIcon import to.bitkit.ui.shared.util.screen +import to.bitkit.ui.openNotificationSettings import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors -import to.bitkit.ui.utils.NotificationUtils import to.bitkit.ui.utils.RequestNotificationPermissions import to.bitkit.viewmodels.SettingsViewModel @@ -52,7 +52,7 @@ fun BackgroundPaymentsSettings( hasPermission = notificationsGranted, showDetails = showNotificationDetails, onBack = onBack, - onSystemSettingsClick = { NotificationUtils.openNotificationSettings(context) }, + onSystemSettingsClick = context::openNotificationSettings, toggleNotificationDetails = settingsViewModel::toggleNotificationDetails, ) } diff --git a/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt b/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt deleted file mode 100644 index e74efc74e..000000000 --- a/app/src/main/java/to/bitkit/ui/utils/NotificationUtils.kt +++ /dev/null @@ -1,45 +0,0 @@ -package to.bitkit.ui.utils - -import android.Manifest.permission.POST_NOTIFICATIONS -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.os.Build -import android.provider.Settings -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat -import to.bitkit.utils.Logger - -object NotificationUtils { - /** - * Opens the Android system notification settings for the app. - * On Android 8.0+ (API 26+), opens the app's notification settings. - * On older versions, opens the general app settings. - */ - fun openNotificationSettings(context: Context) { - val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { - putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) - } - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - runCatching { - context.startActivity(intent) - }.onFailure { - Logger.error("Failed to open notification settings", e = it, context = "NotificationUtils") - } - } - - /** - * Checks if notification permissions are granted. - * For Android 13+ (API 33+), checks the POST_NOTIFICATIONS permission. - * For older versions, checks if notifications are enabled via NotificationManagerCompat. - */ - fun areNotificationsEnabled(context: Context): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - ContextCompat.checkSelfPermission(context, POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED - } else { - NotificationManagerCompat.from(context).areNotificationsEnabled() - } - } -} diff --git a/app/src/main/java/to/bitkit/ui/utils/RequestNotificationPermissions.kt b/app/src/main/java/to/bitkit/ui/utils/RequestNotificationPermissions.kt index 490ff9d03..978554396 100644 --- a/app/src/main/java/to/bitkit/ui/utils/RequestNotificationPermissions.kt +++ b/app/src/main/java/to/bitkit/ui/utils/RequestNotificationPermissions.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner +import to.bitkit.ui.areNotificationsEnabled @Composable fun RequestNotificationPermissions( @@ -30,7 +31,7 @@ fun RequestNotificationPermissions( val requiresPermission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU var isGranted by remember { - mutableStateOf(NotificationUtils.areNotificationsEnabled(context)) + mutableStateOf(context.areNotificationsEnabled()) } // Permission request launcher @@ -43,7 +44,7 @@ fun RequestNotificationPermissions( // Request permission on first composition if needed LaunchedEffect(Unit) { - val currentPermissionState = NotificationUtils.areNotificationsEnabled(context) + val currentPermissionState = context.areNotificationsEnabled() isGranted = currentPermissionState currentOnPermissionChange(currentPermissionState) @@ -56,7 +57,7 @@ fun RequestNotificationPermissions( DisposableEffect(lifecycleOwner) { val observer = LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_RESUME) { - val currentPermissionState = NotificationUtils.areNotificationsEnabled(context) + val currentPermissionState = context.areNotificationsEnabled() if (currentPermissionState != isGranted) { isGranted = currentPermissionState currentOnPermissionChange(currentPermissionState) From 2b94b6f5f9b19cfbfb7b8d041cc21ee77b4078eb Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 06:05:40 +0100 Subject: [PATCH 12/19] feat: localize NodeLifecycleState strings --- .../to/bitkit/models/NodeLifecycleState.kt | 21 ++++++++++--------- .../main/java/to/bitkit/ui/NodeInfoScreen.kt | 3 ++- .../main/java/to/bitkit/ui/Notifications.kt | 3 +-- .../ui/settings/appStatus/AppStatusScreen.kt | 3 +-- .../settings/appStatus/AppStatusViewModel.kt | 2 +- app/src/main/res/values/strings.xml | 6 ++++++ .../appStatus/AppStatusViewModelTest.kt | 5 +++++ 7 files changed, 27 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/to/bitkit/models/NodeLifecycleState.kt b/app/src/main/java/to/bitkit/models/NodeLifecycleState.kt index ab8cf7694..1c5e92a16 100644 --- a/app/src/main/java/to/bitkit/models/NodeLifecycleState.kt +++ b/app/src/main/java/to/bitkit/models/NodeLifecycleState.kt @@ -1,5 +1,8 @@ package to.bitkit.models +import android.content.Context +import to.bitkit.R + sealed class NodeLifecycleState { data object Stopped : NodeLifecycleState() data object Starting : NodeLifecycleState() @@ -14,16 +17,14 @@ sealed class NodeLifecycleState { fun isRunning() = this is Running fun canRun() = this.isRunningOrStarting() || this is Initializing - // TODO add missing localized texts - val uiText: String - get() = when (this) { - is Stopped -> "Stopped" - is Starting -> "Starting" - is Running -> "Running" - is Stopping -> "Stopping" - is ErrorStarting -> "Error starting: ${cause.message}" - is Initializing -> "Setting up wallet..." - } + fun uiText(context: Context): String = when (this) { + is Stopped -> context.getString(R.string.other__node_stopped) + is Starting -> context.getString(R.string.other__node_starting) + is Running -> context.getString(R.string.other__node_running) + is Stopping -> context.getString(R.string.other__node_stopping) + is ErrorStarting -> context.getString(R.string.other__node_error_starting, cause.message ?: "") + is Initializing -> context.getString(R.string.other__node_initializing) + } fun asHealth() = when (this) { Running -> HealthState.READY diff --git a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt index eef545a3f..ff439a5b7 100644 --- a/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt +++ b/app/src/main/java/to/bitkit/ui/NodeInfoScreen.kt @@ -191,11 +191,12 @@ private fun NodeStateSection( nodeLifecycleState: NodeLifecycleState, nodeStatus: NodeStatus?, ) { + val context = LocalContext.current Column(modifier = Modifier.fillMaxWidth()) { SectionHeader("Node State") SettingsTextButtonRow( title = stringResource(R.string.lightning__status), - value = nodeLifecycleState.uiText, + value = nodeLifecycleState.uiText(context), ) nodeStatus?.let { status -> diff --git a/app/src/main/java/to/bitkit/ui/Notifications.kt b/app/src/main/java/to/bitkit/ui/Notifications.kt index a41717f82..029472950 100644 --- a/app/src/main/java/to/bitkit/ui/Notifications.kt +++ b/app/src/main/java/to/bitkit/ui/Notifications.kt @@ -1,7 +1,6 @@ package to.bitkit.ui -import android.Manifest -import android.Manifest.* +import android.Manifest.permission import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent diff --git a/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusScreen.kt b/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusScreen.kt index 9fe6a8799..3f1e8c174 100644 --- a/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusScreen.kt +++ b/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusScreen.kt @@ -31,7 +31,6 @@ import to.bitkit.R import to.bitkit.ext.startActivityAppSettings import to.bitkit.ext.toLocalizedTimestamp import to.bitkit.models.HealthState -import to.bitkit.models.NodeLifecycleState import to.bitkit.repositories.AppHealthState import to.bitkit.ui.Routes import to.bitkit.ui.components.BodyMSB @@ -262,7 +261,7 @@ private fun Preview() { backups = HealthState.READY, ), backupSubtitle = now().minus(3.minutes).toEpochMilliseconds().toLocalizedTimestamp(), - nodeSubtitle = NodeLifecycleState.Running.uiText, + nodeSubtitle = "Running", ), ) } diff --git a/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusViewModel.kt b/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusViewModel.kt index 44199deca..5c2f1d03c 100644 --- a/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/settings/appStatus/AppStatusViewModel.kt @@ -48,7 +48,7 @@ class AppStatusViewModel @Inject constructor( backupSubtitle = computeBackupSubtitle(healthState.backups, backupStatuses), nodeSubtitle = when (healthState.node) { HealthState.ERROR -> context.getString(R.string.settings__status__lightning_node__error) - else -> lightningState.nodeLifecycleState.uiText + else -> lightningState.nodeLifecycleState.uiText(context) }, ) }.collect { newState -> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6305c7dc5..a6cfe54f2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -409,6 +409,12 @@ Incorrect LNURL withdraw params, min/max not set correctly. Withdraw Requested Your withdraw was successfully requested. Waiting for payment. + Error starting: %1$s + Setting up wallet… + Running + Starting + Stopped + Stopping Open Phone Settings Transfer Failed Unable to add LSP node as a peer at this time. diff --git a/app/src/test/java/to/bitkit/ui/settings/appStatus/AppStatusViewModelTest.kt b/app/src/test/java/to/bitkit/ui/settings/appStatus/AppStatusViewModelTest.kt index 8cb5bf270..dc5ff93a1 100644 --- a/app/src/test/java/to/bitkit/ui/settings/appStatus/AppStatusViewModelTest.kt +++ b/app/src/test/java/to/bitkit/ui/settings/appStatus/AppStatusViewModelTest.kt @@ -36,6 +36,11 @@ class AppStatusViewModelTest : BaseUnitTest() { fun setUp() { whenever(context.getString(R.string.settings__status__backup__error)).thenReturn(failedBackupSubtitle) whenever(context.getString(R.string.settings__status__backup__ready)).thenReturn(readyBackupSubtitle) + whenever(context.getString(R.string.other__node_stopped)).thenReturn("Stopped") + whenever(context.getString(R.string.other__node_starting)).thenReturn("Starting") + whenever(context.getString(R.string.other__node_running)).thenReturn("Running") + whenever(context.getString(R.string.other__node_stopping)).thenReturn("Stopping") + whenever(context.getString(R.string.other__node_initializing)).thenReturn("Setting up wallet…") whenever(healthRepo.healthState).thenReturn(MutableStateFlow(AppHealthState())) whenever(lightningRepo.lightningState).thenReturn(MutableStateFlow(LightningState())) whenever(cacheStore.backupStatuses).thenReturn(flowOf(emptyMap())) From 962a0305ba79d008537a9586df679119d6e0a21f Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 19:26:49 +0100 Subject: [PATCH 13/19] chore: update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6da892352..fb2999375 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ google-services.json .env *.keystore !debug.keystore -keystore.properties +keystore.* +!keystore.properties.template From 40654c11144f62b6154b82cc1cf4e36c21c62b52 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Tue, 6 Jan 2026 19:56:04 +0100 Subject: [PATCH 14/19] chore: update readme --- README.md | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 88ce6a21d..9d2c1bf3e 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ This repository contains a **new native Android app** which is **not ready for p #### 1. Firebase Configuration -Download `google-services.json` from the Firebase Console for each build flavor: -- **Dev/Testnet**: Place in `app/` (default location) -- **Mainnet**: Place in `app/src/mainnet/google-services.json` +Download `google-services.json` from the Firebase Console for each of the following build flavor groups,: +- dev/tnet/mainnetDebug: Place in `app/google-services.json` +- mainnetRelease: Place in `app/src/mainnetRelease/google-services.json` > **Note**: Each flavor requires its own Firebase project configuration. The mainnet flavor will fail to build without its dedicated `google-services.json` file. @@ -113,16 +113,31 @@ The build config supports building 3 different apps for the 3 bitcoin networks ( - `mainnet` flavour = mainnet - `tnet` flavour = testnet -### Build for Mainnet +### Build for Internal Testing -To build the mainnet flavor: +**Prerequisites** +Setup the signing config: +- Add the keystore file to root dir (i.e. `internal.keystore`) +- Setup `keystore.properties` file in root dir (`cp keystore.properties.template keystore.properties`) + +**Routine** +Increment `versionCode` and `versionName` in `app/build.gradle.kts`, then run: ```sh -./gradlew assembleMainnetDebug # debug build -./gradlew assembleMainnetRelease # release build (requires signing config) +./gradlew assembleDevRelease +# ./gradlew assembleRelease # for all flavors ``` -> **Important**: Ensure `app/src/mainnet/google-services.json` exists before building. See [Firebase Configuration](#1-firebase-configuration). +APK is generated in `app/build/outputs/apk/_flavor_/release`. (`_flavor_` can be any of 'dev', 'mainnet', 'tnet'). +Example for dev: `app/build/outputs/apk/dev/release` + +### Build for Release + +To build the mainnet flavor for release run: + +```sh +./gradlew assembleMainnetRelease +``` ### Build for E2E Testing @@ -153,24 +168,6 @@ By default, geoblocking checks via API are enabled. To disable at build time, us GEO=false E2E=true ./gradlew assembleDevRelease ``` -### Build for Release - -**Prerequisites** -Setup the signing config: -- Add the keystore file to root dir (i.e. `release.keystore`) -- Setup `keystore.properties` file in root dir (`cp keystore.properties.template keystore.properties`) - -**Routine** - -Increment `versionCode` and `versionName` in `app/build.gradle.kts`, then run: -```sh -./gradlew assembleDevRelease -# ./gradlew assembleRelease # for all flavors -``` - -APK is generated in `app/build/outputs/apk/_flavor_/release`. (`_flavor_` can be any of 'dev', 'mainnet', 'tnet'). -Example for dev: `app/build/outputs/apk/dev/release` - ## Contributing ### AI Code Review with Claude From 8c59952444ed9a77813f3777d7c0eaf208ec4725 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 7 Jan 2026 00:59:24 +0100 Subject: [PATCH 15/19] feat: dynamic boost fee time estimates --- app/src/main/java/to/bitkit/models/FeeRate.kt | 15 +- .../wallets/activity/ActivityDetailScreen.kt | 5 +- .../activity/components/ActivityRow.kt | 10 +- .../ui/sheets/BoostTransactionViewModel.kt | 13 +- .../java/to/bitkit/ui/WalletViewModelTest.kt | 6 + .../sheets/BoostTransactionViewModelTest.kt | 203 ++++++++++++------ 6 files changed, 169 insertions(+), 83 deletions(-) diff --git a/app/src/main/java/to/bitkit/models/FeeRate.kt b/app/src/main/java/to/bitkit/models/FeeRate.kt index 4c0b6328d..d4a8785de 100644 --- a/app/src/main/java/to/bitkit/models/FeeRate.kt +++ b/app/src/main/java/to/bitkit/models/FeeRate.kt @@ -1,10 +1,9 @@ package to.bitkit.models +import android.content.Context import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource import com.synonym.bitkitcore.FeeRates import to.bitkit.R import to.bitkit.ui.theme.Colors @@ -81,16 +80,12 @@ enum class FeeRate( } } - @Composable - fun getFeeDescription( + fun Context.getFeeShortDescription( feeRate: ULong, - feeEstimates: FeeRates?, + feeRates: FeeRates?, ): String { - val feeRateEnum = feeEstimates?.let { - fromSatsPerVByte(feeRate, it) - } ?: NORMAL - - return stringResource(feeRateEnum.shortDescription) + val feeRateEnum = feeRates?.let { fromSatsPerVByte(feeRate, it) } ?: NORMAL + return getString(feeRateEnum.shortDescription) } } } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt index 63886cd13..b3568a750 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/ActivityDetailScreen.kt @@ -57,7 +57,7 @@ import to.bitkit.ext.timestamp import to.bitkit.ext.toActivityItemDate import to.bitkit.ext.toActivityItemTime import to.bitkit.ext.totalValue -import to.bitkit.models.FeeRate +import to.bitkit.models.FeeRate.Companion.getFeeShortDescription import to.bitkit.models.Toast import to.bitkit.ui.Routes import to.bitkit.ui.appViewModel @@ -739,7 +739,8 @@ private fun StatusSection( var statusTestTag: String? = null if (item.v1.isTransfer) { - val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) + val context = LocalContext.current + val duration = context.getFeeShortDescription(item.v1.feeRate, feeRates) statusText = stringResource(R.string.wallet__activity_transfer_pending) .replace("{duration}", duration) statusTestTag = "StatusTransfer" diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt index 81962392a..f6681ec7e 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/activity/components/ActivityRow.kt @@ -17,6 +17,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource @@ -37,7 +38,7 @@ import to.bitkit.ext.rawId import to.bitkit.ext.timestamp import to.bitkit.ext.totalValue import to.bitkit.ext.txType -import to.bitkit.models.FeeRate +import to.bitkit.models.FeeRate.Companion.getFeeShortDescription import to.bitkit.models.PrimaryDisplay import to.bitkit.models.formatToModernDisplay import to.bitkit.ui.LocalCurrencies @@ -117,6 +118,7 @@ fun ActivityRow( isTransfer = isTransfer, isCpfpChild = isCpfpChild ) + val context = LocalContext.current val subtitleText = when (item) { is Activity.Lightning -> item.v1.message.ifEmpty { formattedTime(timestamp) } is Activity.Onchain -> { @@ -128,7 +130,7 @@ fun ActivityRow( isTransfer && isSent -> if (item.v1.confirmed) { stringResource(R.string.wallet__activity_transfer_spending_done) } else { - val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) + val duration = context.getFeeShortDescription(item.v1.feeRate, feeRates) stringResource(R.string.wallet__activity_transfer_spending_pending) .replace("{duration}", duration) } @@ -136,7 +138,7 @@ fun ActivityRow( isTransfer && !isSent -> if (item.v1.confirmed) { stringResource(R.string.wallet__activity_transfer_savings_done) } else { - val duration = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) + val duration = context.getFeeShortDescription(item.v1.feeRate, feeRates) stringResource(R.string.wallet__activity_transfer_savings_pending) .replace("{duration}", duration) } @@ -144,7 +146,7 @@ fun ActivityRow( confirmed == true -> formattedTime(timestamp) else -> { - val feeDescription = FeeRate.getFeeDescription(item.v1.feeRate, feeRates) + val feeDescription = context.getFeeShortDescription(item.v1.feeRate, feeRates) stringResource(R.string.wallet__activity_confirms_in) .replace("{feeRateDescription}", feeDescription) } diff --git a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt index 38a6c62dd..e2b5d8004 100644 --- a/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/sheets/BoostTransactionViewModel.kt @@ -1,11 +1,13 @@ package to.bitkit.ui.sheets +import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.synonym.bitkitcore.Activity import com.synonym.bitkitcore.OnchainActivity import com.synonym.bitkitcore.PaymentType import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asSharedFlow @@ -16,8 +18,10 @@ import org.lightningdevkit.ldknode.Txid import to.bitkit.ext.BoostType import to.bitkit.ext.boostType import to.bitkit.ext.nowTimestamp +import to.bitkit.models.FeeRate.Companion.getFeeShortDescription import to.bitkit.models.TransactionSpeed import to.bitkit.repositories.ActivityRepo +import to.bitkit.repositories.BlocktankRepo import to.bitkit.repositories.LightningRepo import to.bitkit.repositories.WalletRepo import to.bitkit.utils.Logger @@ -26,9 +30,11 @@ import javax.inject.Inject @HiltViewModel class BoostTransactionViewModel @Inject constructor( + @ApplicationContext private val context: Context, private val lightningRepo: LightningRepo, private val walletRepo: WalletRepo, private val activityRepo: ActivityRepo, + private val blocktankRepo: BlocktankRepo, ) : ViewModel() { private val _uiState = MutableStateFlow(BoostTransactionUiState()) @@ -37,7 +43,7 @@ class BoostTransactionViewModel @Inject constructor( private val _boostTransactionEffect = MutableSharedFlow(extraBufferCapacity = 1) val boostTransactionEffect = _boostTransactionEffect.asSharedFlow() - private companion object { + companion object { const val TAG = "BoostTransactionViewModel" const val MAX_FEE_PERCENTAGE = 0.5 const val MAX_FEE_RATE = 100UL @@ -133,6 +139,8 @@ class BoostTransactionViewModel @Inject constructor( val currentFee = activity?.v1?.fee ?: 0u val isIncreaseEnabled = totalFee < maxTotalFee && feeRate < MAX_FEE_RATE val isDecreaseEnabled = totalFee > currentFee && feeRate > minFeeRate + val feeRates = blocktankRepo.blocktankState.value.info?.onchain?.feeRates + val estimateTime = context.getFeeShortDescription(feeRate, feeRates) _uiState.update { it.copy( @@ -141,6 +149,7 @@ class BoostTransactionViewModel @Inject constructor( increaseEnabled = isIncreaseEnabled, decreaseEnabled = isDecreaseEnabled, loading = false, + estimateTime = estimateTime, ) } } @@ -370,6 +379,6 @@ data class BoostTransactionUiState( val increaseEnabled: Boolean = true, val boosting: Boolean = false, val loading: Boolean = false, - val estimateTime: String = "±10-20 minutes", // TODO: Implement dynamic time estimation + val estimateTime: String = "", val isRbf: Boolean = false, ) diff --git a/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt b/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt index e3f96a8af..df2b089cd 100644 --- a/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt +++ b/app/src/test/java/to/bitkit/ui/WalletViewModelTest.kt @@ -1,5 +1,6 @@ package to.bitkit.ui +import android.content.Context import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.runBlocking @@ -33,6 +34,7 @@ import to.bitkit.viewmodels.WalletViewModel class WalletViewModelTest : BaseUnitTest() { private lateinit var sut: WalletViewModel + private val context = mock() private val walletRepo = mock() private val lightningRepo = mock() private val settingsStore = mock() @@ -47,11 +49,13 @@ class WalletViewModelTest : BaseUnitTest() { @Before fun setUp() = runBlocking { + whenever(context.getString(any())).thenReturn("") whenever(walletRepo.walletState).thenReturn(walletState) whenever(lightningRepo.lightningState).thenReturn(lightningState) whenever(migrationService.isMigrationChecked()).thenReturn(true) sut = WalletViewModel( + context = context, bgDispatcher = testDispatcher, walletRepo = walletRepo, lightningRepo = lightningRepo, @@ -235,6 +239,7 @@ class WalletViewModelTest : BaseUnitTest() { .thenReturn(Result.success(Unit)) val testSut = WalletViewModel( + context = context, bgDispatcher = testDispatcher, walletRepo = testWalletRepo, lightningRepo = testLightningRepo, @@ -274,6 +279,7 @@ class WalletViewModelTest : BaseUnitTest() { .thenReturn(Result.success(Unit)) val testSut = WalletViewModel( + context = context, bgDispatcher = testDispatcher, walletRepo = testWalletRepo, lightningRepo = testLightningRepo, diff --git a/app/src/test/java/to/bitkit/ui/sheets/BoostTransactionViewModelTest.kt b/app/src/test/java/to/bitkit/ui/sheets/BoostTransactionViewModelTest.kt index c726bed62..8b9e64ff1 100644 --- a/app/src/test/java/to/bitkit/ui/sheets/BoostTransactionViewModelTest.kt +++ b/app/src/test/java/to/bitkit/ui/sheets/BoostTransactionViewModelTest.kt @@ -1,10 +1,16 @@ package to.bitkit.ui.sheets +import android.content.Context import app.cash.turbine.test import com.synonym.bitkitcore.Activity +import com.synonym.bitkitcore.FeeRates +import com.synonym.bitkitcore.IBtInfo +import com.synonym.bitkitcore.IBtInfoOnchain import com.synonym.bitkitcore.OnchainActivity import com.synonym.bitkitcore.PaymentType import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -15,55 +21,79 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever -import org.mockito.kotlin.wheneverBlocking +import to.bitkit.R import to.bitkit.ext.create import to.bitkit.models.TransactionSpeed import to.bitkit.repositories.ActivityRepo +import to.bitkit.repositories.BlocktankRepo +import to.bitkit.repositories.BlocktankState import to.bitkit.repositories.LightningRepo import to.bitkit.repositories.WalletRepo import to.bitkit.test.BaseUnitTest +import to.bitkit.ui.sheets.BoostTransactionViewModel.Companion.MAX_FEE_RATE import kotlin.test.assertEquals import kotlin.test.assertFalse import kotlin.test.assertTrue class BoostTransactionViewModelTest : BaseUnitTest() { - private lateinit var sut: BoostTransactionViewModel - private val lightningRepo: LightningRepo = mock() - private val walletRepo: WalletRepo = mock() - private val activityRepo: ActivityRepo = mock() + private val context = mock() + private val lightningRepo = mock() + private val walletRepo = mock() + private val activityRepo = mock() + private val blocktankRepo = mock() + + private val onchain = mock() + private val mockBtInfo = mock() + private val feeRates = FeeRates(fast = 20u, mid = 10u, slow = 5u) + private val blocktankState = MutableStateFlow(BlocktankState(info = mockBtInfo)) // Test data private val mockTxId = "test_txid_123" - private val mockNewTxId = "new_txid_456" - private val mockAddress = "bc1rt1test123" - private val testFeeRate = 10UL - private val testTotalFee = 1000UL + private val newTxId = "new_txid_456" + private val address = "bc1rt1test123" + private val feeRate = 10UL + private val totalFee = 1000UL private val testValue = 50000UL - private val mockOnchainActivity = OnchainActivity.create( + private val onchainActivity = OnchainActivity.create( id = "test_id", txType = PaymentType.SENT, txId = mockTxId, value = testValue, fee = 500UL, - address = mockAddress, + address = address, timestamp = 1234567890UL, feeRate = 10UL, ) - private val mockActivitySent = Activity.Onchain(v1 = mockOnchainActivity) + private val activitySent = Activity.Onchain(onchainActivity) + + private val fastFeeTime = "±10m" + private val normalFeeTime = "±20m" + private val flowFeeTime = "±1h" + private val minFeeTime = "+2h" @Before - fun setUp() { + fun setUp() = runBlocking { + whenever(context.getString(R.string.fee__fast__shortDescription)).thenReturn(fastFeeTime) + whenever(context.getString(R.string.fee__normal__shortDescription)).thenReturn(normalFeeTime) + whenever(context.getString(R.string.fee__slow__shortDescription)).thenReturn(flowFeeTime) + whenever(context.getString(R.string.fee__minimum__shortDescription)).thenReturn(minFeeTime) + whenever(onchain.feeRates).thenReturn(feeRates) + whenever(mockBtInfo.onchain).thenReturn(onchain) + whenever(blocktankRepo.blocktankState).thenReturn(blocktankState) + whenever(lightningRepo.listSpendableOutputs()).thenReturn(Result.success(emptyList())) + whenever(lightningRepo.syncAsync()).thenReturn(Job()) + sut = BoostTransactionViewModel( + context = context, lightningRepo = lightningRepo, walletRepo = walletRepo, - activityRepo = activityRepo + activityRepo = activityRepo, + blocktankRepo = blocktankRepo, ) - wheneverBlocking { lightningRepo.listSpendableOutputs() }.thenReturn(Result.success(emptyList())) - whenever(lightningRepo.syncAsync()).thenReturn(Job()) } @Test @@ -82,14 +112,13 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `setupActivity should set loading state initially`() = runTest { - whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())) - .thenReturn(Result.success(testFeeRate)) + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(feeRate)) whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) - .thenReturn(Result.success(testTotalFee)) + .thenReturn(Result.success(totalFee)) sut.uiState.test { awaitItem() // initial state - sut.setupActivity(mockActivitySent) + sut.setupActivity(activitySent) val loadingState = awaitItem() assertTrue(loadingState.loading) @@ -99,12 +128,11 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `setupActivity should call correct repository methods for sent transaction`() = runTest { - whenever(lightningRepo.getFeeRateForSpeed(eq(TransactionSpeed.Fast), anyOrNull())) - .thenReturn(Result.success(testFeeRate)) + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(feeRate)) whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) - .thenReturn(Result.success(testTotalFee)) + .thenReturn(Result.success(totalFee)) - sut.setupActivity(mockActivitySent) + sut.setupActivity(activitySent) verify(lightningRepo).getFeeRateForSpeed(eq(TransactionSpeed.Fast), anyOrNull()) verify(lightningRepo).calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull()) @@ -112,12 +140,10 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `setupActivity should call CPFP method for received transaction`() = runTest { - val receivedActivity = Activity.Onchain( - v1 = mockOnchainActivity.copy(txType = PaymentType.RECEIVED) - ) + val receivedActivity = Activity.Onchain(onchainActivity.copy(txType = PaymentType.RECEIVED)) whenever(lightningRepo.calculateCpfpFeeRate(eq(mockTxId))) - .thenReturn(Result.success(testFeeRate)) + .thenReturn(Result.success(feeRate)) sut.setupActivity(receivedActivity) @@ -146,12 +172,11 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `onChangeAmount should emit OnMaxFee when at maximum rate`() = runTest { - whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())) - .thenReturn(Result.success(100UL)) // MAX_FEE_RATE + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(MAX_FEE_RATE)) whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) - .thenReturn(Result.success(testTotalFee)) + .thenReturn(Result.success(totalFee)) - sut.setupActivity(mockActivitySent) + sut.setupActivity(activitySent) sut.boostTransactionEffect.test { sut.onChangeAmount(increase = true) @@ -161,12 +186,11 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `onChangeAmount should emit OnMinFee when at minimum rate`() = runTest { - whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())) - .thenReturn(Result.success(1UL)) // MIN_FEE_RATE + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(1UL)) // MIN_FEE_RATE whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) - .thenReturn(Result.success(testTotalFee)) + .thenReturn(Result.success(totalFee)) - sut.setupActivity(mockActivitySent) + sut.setupActivity(activitySent) sut.boostTransactionEffect.test { sut.onChangeAmount(increase = false) @@ -176,47 +200,30 @@ class BoostTransactionViewModelTest : BaseUnitTest() { @Test fun `setupActivity failure should emit OnBoostFailed`() = runTest { - whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())) - .thenReturn(Result.failure(Exception("Fee estimation failed"))) + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.failure(Exception("error"))) sut.boostTransactionEffect.test { - sut.setupActivity(mockActivitySent) + sut.setupActivity(activitySent) assertEquals(BoostTransactionEffects.OnBoostFailed, awaitItem()) } } @Test fun `successful CPFP boost should call correct repository methods`() = runTest { - val receivedActivity = Activity.Onchain( - v1 = mockOnchainActivity.copy(txType = PaymentType.RECEIVED) - ) + val receivedActivity = Activity.Onchain(onchainActivity.copy(txType = PaymentType.RECEIVED)) - whenever(lightningRepo.calculateCpfpFeeRate(any())) - .thenReturn(Result.success(testFeeRate)) + whenever(lightningRepo.calculateCpfpFeeRate(any())).thenReturn(Result.success(feeRate)) whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) - .thenReturn(Result.success(testTotalFee)) - whenever(walletRepo.getOnchainAddress()) - .thenReturn(mockAddress) - whenever(lightningRepo.accelerateByCpfp(any(), any(), any())) - .thenReturn(Result.success(mockNewTxId)) - - val newActivity = mockOnchainActivity.copy( - txType = PaymentType.SENT, - txId = mockNewTxId, - isBoosted = true - ) + .thenReturn(Result.success(totalFee)) + whenever(walletRepo.getOnchainAddress()).thenReturn(address) + whenever(lightningRepo.accelerateByCpfp(any(), any(), any())).thenReturn(Result.success(newTxId)) - whenever( - activityRepo.findActivityByPaymentId( - paymentHashOrTxId = any(), - type = any(), - txType = any(), - retry = any(), - ) - ).thenReturn(Result.success(Activity.Onchain(v1 = newActivity))) + val newActivity = onchainActivity.copy(txType = PaymentType.SENT, txId = newTxId, isBoosted = true) - whenever(activityRepo.updateActivity(any(), any(), any())) - .thenReturn(Result.success(Unit)) + whenever(activityRepo.findActivityByPaymentId(any(), any(), any(), any())) + .thenReturn(Result.success(Activity.Onchain(newActivity))) + + whenever(activityRepo.updateActivity(any(), any(), any())).thenReturn(Result.success(Unit)) sut.setupActivity(receivedActivity) @@ -230,4 +237,70 @@ class BoostTransactionViewModelTest : BaseUnitTest() { verify(activityRepo).updateActivity(any(), any(), any()) verify(activityRepo, never()).deleteActivity(any()) } + + // region estimateTime dynamic tier tests + + @Test + fun `estimateTime shows fast description when fee rate at or above fast threshold`() = runTest { + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(25UL)) + whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) + .thenReturn(Result.success(totalFee)) + + sut.uiState.test { + awaitItem() + sut.setupActivity(activitySent) + awaitItem() + val state = awaitItem() + assertEquals(fastFeeTime, state.estimateTime) + } + } + + @Test + fun `estimateTime shows normal description when fee rate between mid and fast`() = runTest { + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(15UL)) + whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) + .thenReturn(Result.success(totalFee)) + + sut.uiState.test { + awaitItem() + sut.setupActivity(activitySent) + awaitItem() + val state = awaitItem() + assertEquals(normalFeeTime, state.estimateTime) + } + } + + @Test + fun `estimateTime shows slow description when fee rate between slow and mid`() = runTest { + val lowFeeActivity = Activity.Onchain(onchainActivity.copy(feeRate = 1UL)) + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(7UL)) + whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) + .thenReturn(Result.success(totalFee)) + + sut.uiState.test { + awaitItem() // initial state + sut.setupActivity(lowFeeActivity) + awaitItem() // loading state + val state = awaitItem() + assertEquals(flowFeeTime, state.estimateTime) + } + } + + @Test + fun `estimateTime shows minimum description when fee rate below slow threshold`() = runTest { + val lowFeeActivity = Activity.Onchain(onchainActivity.copy(feeRate = 1UL)) + whenever(lightningRepo.getFeeRateForSpeed(any(), anyOrNull())).thenReturn(Result.success(3UL)) + whenever(lightningRepo.calculateTotalFee(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())) + .thenReturn(Result.success(totalFee)) + + sut.uiState.test { + awaitItem() // initial state + sut.setupActivity(lowFeeActivity) + awaitItem() // loading state + val state = awaitItem() + assertEquals(minFeeTime, state.estimateTime) + } + } + + // endregion } From c23f3f63efe3d2ed0d4ba545a472feb475847c56 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 7 Jan 2026 02:09:01 +0100 Subject: [PATCH 16/19] feat: weather widget API calls caching --- .../to/bitkit/data/widgets/WeatherService.kt | 62 ++++++++++++------- app/src/main/java/to/bitkit/ext/DateTime.kt | 3 + 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/to/bitkit/data/widgets/WeatherService.kt b/app/src/main/java/to/bitkit/data/widgets/WeatherService.kt index 4c5f8b3e1..d3e516b51 100644 --- a/app/src/main/java/to/bitkit/data/widgets/WeatherService.kt +++ b/app/src/main/java/to/bitkit/data/widgets/WeatherService.kt @@ -10,6 +10,7 @@ import to.bitkit.data.dto.FeeCondition import to.bitkit.data.dto.FeeEstimates import to.bitkit.data.dto.WeatherDTO import to.bitkit.env.Env +import to.bitkit.ext.nowMs import to.bitkit.models.WidgetType import to.bitkit.repositories.CurrencyRepo import to.bitkit.utils.AppError @@ -18,26 +19,42 @@ import java.math.BigDecimal import javax.inject.Inject import javax.inject.Singleton import kotlin.math.floor +import kotlin.time.Clock +import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes +import kotlin.time.ExperimentalTime +@OptIn(ExperimentalTime::class) @Singleton class WeatherService @Inject constructor( private val client: HttpClient, private val currencyRepo: CurrencyRepo, + private val clock: Clock, ) : WidgetService { override val widgetType = WidgetType.WEATHER override val refreshInterval = 8.minutes - private companion object { + private var cachedFeeEstimates: FeeEstimates? = null + private var feeEstimatesTimestamp: Long = 0L + private var cachedHistoricalData: List? = null + private var historicalDataTimestamp: Long = 0L + + companion object { private const val TAG = "WeatherService" + + @Suppress("SpellCheckingInspection") private const val AVERAGE_SEGWIT_VBYTES_SIZE = 140 private const val USD_GOOD_THRESHOLD = 1.0 // $1 USD threshold for good condition private const val PERCENTILE_LOW = 0.33 private const val PERCENTILE_HIGH = 0.66 private const val USD_CURRENCY = "USD" + private val TTL_FEE_ESTIMATES = 2.minutes + private val TTL_HISTORICAL_DATA = 30.minutes } + private fun isCacheValid(timestamp: Long, ttl: Duration) = clock.nowMs() - timestamp < ttl.inWholeMilliseconds + override suspend fun fetchData(): Result = runCatching { // Fetch fee estimates and historical data in parallel val feeEstimates = getFeeEstimates() @@ -56,34 +73,42 @@ class WeatherService @Inject constructor( nextBlockFee = feeEstimates.fast ) }.onFailure { - Logger.warn(e = it, msg = "Failed to fetch weather data", context = TAG) + Logger.warn("Failed to fetch weather data", e = it, context = TAG) } - private suspend fun getFeeEstimates(): FeeEstimates { // TODO CACHE + private suspend fun getFeeEstimates(): FeeEstimates { + cachedFeeEstimates?.takeIf { isCacheValid(feeEstimatesTimestamp, TTL_FEE_ESTIMATES) }?.let { return it } val response: HttpResponse = client.get("${Env.mempoolBaseUrl}/v1/fees/recommended") return when (response.status.isSuccess()) { - true -> response.body() + true -> response.body().also { + cachedFeeEstimates = it + feeEstimatesTimestamp = clock.nowMs() + } + else -> throw WeatherError.InvalidResponse("Failed to fetch fee estimates: ${response.status.description}") } } - private suspend fun getHistoricalFeeData(): List { // TODO CACHE + private suspend fun getHistoricalFeeData(): List { + cachedHistoricalData?.takeIf { isCacheValid(historicalDataTimestamp, TTL_HISTORICAL_DATA) }?.let { return it } val response: HttpResponse = client.get("${Env.mempoolBaseUrl}/v1/mining/blocks/fee-rates/3m") return when (response.status.isSuccess()) { - true -> response.body>() + true -> response.body>().also { + cachedHistoricalData = it + historicalDataTimestamp = clock.nowMs() + } + else -> throw WeatherError.InvalidResponse( "Failed to fetch historical fee data: ${response.status.description}" ) } } - private suspend fun calculateCondition( + private fun calculateCondition( currentFeeRate: Double, - history: List + history: List, ): FeeCondition { - if (history.isEmpty()) { - return FeeCondition.AVERAGE - } + if (history.isEmpty()) return FeeCondition.AVERAGE // Extract median fees from historical data and sort val historicalFees = history.map { it.avgFee50 }.sorted() @@ -94,11 +119,10 @@ class WeatherService @Inject constructor( // Check USD threshold first val avgFeeSats = currentFeeRate * AVERAGE_SEGWIT_VBYTES_SIZE - val avgFeeUsd = currencyRepo.convertSatsToFiat(avgFeeSats.toLong(), currency = USD_CURRENCY).getOrNull() ?: return FeeCondition.AVERAGE + val avgFeeUsd = currencyRepo.convertSatsToFiat(avgFeeSats.toLong(), currency = USD_CURRENCY).getOrNull() + ?: return FeeCondition.AVERAGE - if (avgFeeUsd.value <= BigDecimal(USD_GOOD_THRESHOLD)) { - return FeeCondition.GOOD - } + if (avgFeeUsd.value <= BigDecimal(USD_GOOD_THRESHOLD)) return FeeCondition.GOOD // Determine condition based on percentiles return when { @@ -108,16 +132,12 @@ class WeatherService @Inject constructor( } } - private suspend fun formatFeeForDisplay(satoshis: Int): String { + private fun formatFeeForDisplay(satoshis: Int): String { val usdValue = currencyRepo.convertSatsToFiat(satoshis.toLong(), currency = USD_CURRENCY).getOrNull() return usdValue?.formatted.orEmpty() } } -/** - * Weather-specific error types - */ sealed class WeatherError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : WeatherError(message) - data class ConversionError(override val message: String) : WeatherError(message) + class InvalidResponse(override val message: String) : WeatherError(message) } diff --git a/app/src/main/java/to/bitkit/ext/DateTime.kt b/app/src/main/java/to/bitkit/ext/DateTime.kt index bea254c2b..5ed0b1750 100644 --- a/app/src/main/java/to/bitkit/ext/DateTime.kt +++ b/app/src/main/java/to/bitkit/ext/DateTime.kt @@ -36,6 +36,9 @@ import kotlin.time.Instant as KInstant @OptIn(ExperimentalTime::class) fun nowMillis(clock: Clock = Clock.System): Long = clock.now().toEpochMilliseconds() +@OptIn(ExperimentalTime::class) +fun Clock.nowMs(): Long = now().toEpochMilliseconds() + fun nowTimestamp(): Instant = Instant.now().truncatedTo(ChronoUnit.SECONDS) fun Instant.formatted(pattern: String = DatePattern.DATE_TIME): String { From d3a5abe6a44f3df521bebf2479e756a1515b5897 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 7 Jan 2026 02:33:44 +0100 Subject: [PATCH 17/19] chore: cleanup todos --- app/src/main/java/to/bitkit/env/Env.kt | 4 ++-- app/src/main/java/to/bitkit/ext/DateTime.kt | 1 - app/src/main/java/to/bitkit/repositories/WalletRepo.kt | 4 ++-- app/src/main/java/to/bitkit/repositories/WidgetsRepo.kt | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index c725f6884..31f1574cd 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -20,7 +20,7 @@ internal object Env { val e2eBackend = BuildConfig.E2E_BACKEND.lowercase() val network = Network.valueOf(BuildConfig.NETWORK) val locales = BuildConfig.LOCALES.split(",") - val walletSyncIntervalSecs = 10_uL // TODO review + val walletSyncIntervalSecs = 10_uL val platform = "Android ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})" const val version = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" @@ -56,7 +56,7 @@ internal object Env { Network.BITCOIN -> ElectrumServers.MAINNET.FULCRUM Network.REGTEST -> if (isE2eLocal) ElectrumServers.REGTEST.LOCAL else ElectrumServers.REGTEST.STAG Network.TESTNET -> ElectrumServers.TESTNET - else -> TODO("${network.name} network not implemented") + else -> throw Error("${network.name} network not implemented") } } diff --git a/app/src/main/java/to/bitkit/ext/DateTime.kt b/app/src/main/java/to/bitkit/ext/DateTime.kt index 5ed0b1750..757024341 100644 --- a/app/src/main/java/to/bitkit/ext/DateTime.kt +++ b/app/src/main/java/to/bitkit/ext/DateTime.kt @@ -111,7 +111,6 @@ fun Long.toRelativeTimeString( fun getDaysInMonth(month: LocalDate): List { val firstDayOfMonth = LocalDate(month.year, month.month, Constants.FIRST_DAY_OF_MONTH) - // FIXME fix month.number val daysInMonth = month.month.toJavaMonth().length(isLeapYear(month.year)) // Get the day of week for the first day (1 = Monday, 7 = Sunday) diff --git a/app/src/main/java/to/bitkit/repositories/WalletRepo.kt b/app/src/main/java/to/bitkit/repositories/WalletRepo.kt index b361e67e9..d46f18eb9 100644 --- a/app/src/main/java/to/bitkit/repositories/WalletRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/WalletRepo.kt @@ -405,7 +405,7 @@ class WalletRepo @Inject constructor( bitcoinAddress = bitcoinAddress, amountSats = amountSats, message = message, - lightningInvoice = lightningInvoice + lightningInvoice = lightningInvoice, ) } @@ -443,7 +443,7 @@ class WalletRepo @Inject constructor( val hash = paymentHash() if (hash != null) return@withContext hash val address = getOnchainAddress() - return@withContext if (address.isEmpty()) null else address + return@withContext address.ifEmpty { null } } // Pre-activity metadata tag management diff --git a/app/src/main/java/to/bitkit/repositories/WidgetsRepo.kt b/app/src/main/java/to/bitkit/repositories/WidgetsRepo.kt index 9d9829127..9bdd491bd 100644 --- a/app/src/main/java/to/bitkit/repositories/WidgetsRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/WidgetsRepo.kt @@ -60,6 +60,7 @@ class WidgetsRepo @Inject constructor( private val _refreshStates = MutableStateFlow( WidgetType.entries.associateWith { false } ) + val refreshStates: StateFlow> = _refreshStates.asStateFlow() init { From 79bb268c38d4ac236a44a8ff47a4d16cf0460ad2 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 7 Jan 2026 02:38:44 +0100 Subject: [PATCH 18/19] chore: remove deprecated LdkMigrationTest.kt --- .../to/bitkit/services/LdkMigrationTest.kt | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 app/src/androidTest/java/to/bitkit/services/LdkMigrationTest.kt diff --git a/app/src/androidTest/java/to/bitkit/services/LdkMigrationTest.kt b/app/src/androidTest/java/to/bitkit/services/LdkMigrationTest.kt deleted file mode 100644 index 51dfbab12..000000000 --- a/app/src/androidTest/java/to/bitkit/services/LdkMigrationTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -package to.bitkit.services - -import android.content.Context -import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import kotlinx.coroutines.runBlocking -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import to.bitkit.data.keychain.Keychain -import to.bitkit.env.Env -import to.bitkit.ext.readAsset -import javax.inject.Inject -import kotlin.test.assertTrue - -@HiltAndroidTest -class LdkMigrationTest { - @get:Rule - var hiltRule = HiltAndroidRule(this) - - @Inject - lateinit var keychain: Keychain - - @Inject - lateinit var lightningService: LightningService - - private val mnemonic = "pool curve feature leader elite dilemma exile toast smile couch crane public" - - private val testContext by lazy { InstrumentationRegistry.getInstrumentation().context } - private val appContext = ApplicationProvider.getApplicationContext() - - @Before - fun init() { - hiltRule.inject() - Env.initAppStoragePath(appContext.filesDir.absolutePath) - runBlocking { keychain.saveString(Keychain.Key.BIP39_MNEMONIC.name, mnemonic) } - } - - @Test - fun nodeShouldStartFromBackupAfterMigration() = runBlocking { -// TODO Fix or remove check on channel size -// val seed = testContext.readAsset("ldk-backup/seed.bin") -// val manager = testContext.readAsset("ldk-backup/manager.bin") -// val monitor = testContext.readAsset("ldk-backup/monitor.bin") -// -// MigrationService(appContext).migrate(seed, manager, listOf(monitor)) -// -// with(lightningService) { -// setup(walletIndex = 0) -// runBlocking { start() } -// -// assertTrue { nodeId == "02cd08b7b375e4263849121f9f0ffb2732a0b88d0fb74487575ac539b374f45a55" } -// assertTrue { channels?.isNotEmpty() == true } -// -// runBlocking { stop() } -// } - } -} From b684ca23bab373b1a4ce178d249c2c2fd737641f Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Mon, 12 Jan 2026 15:53:16 +0100 Subject: [PATCH 19/19] refactor: use class for all errors to fix warnings --- .../java/to/bitkit/data/ChatwootHttpClient.kt | 2 +- .../to/bitkit/data/backup/VssBackupClient.kt | 2 +- .../bitkit/data/backup/VssStoreIdProvider.kt | 3 +- .../to/bitkit/data/widgets/BlocksService.kt | 2 +- .../to/bitkit/data/widgets/NewsService.kt | 2 +- .../to/bitkit/data/widgets/PriceService.kt | 4 +- .../to/bitkit/repositories/BlocktankRepo.kt | 16 +++--- .../to/bitkit/repositories/LightningRepo.kt | 2 +- .../java/to/bitkit/repositories/WalletRepo.kt | 3 +- .../to/bitkit/services/AppUpdaterService.kt | 2 +- .../java/to/bitkit/services/CoreService.kt | 2 +- .../to/bitkit/services/CurrencyService.kt | 4 +- .../to/bitkit/services/LightningService.kt | 56 ++++++++++--------- .../services/LspNotificationsService.kt | 2 +- .../java/to/bitkit/services/RNBackupClient.kt | 18 +++--- app/src/main/java/to/bitkit/utils/Crypto.kt | 26 ++++----- app/src/main/java/to/bitkit/utils/Errors.kt | 38 ++++--------- 17 files changed, 85 insertions(+), 99 deletions(-) diff --git a/app/src/main/java/to/bitkit/data/ChatwootHttpClient.kt b/app/src/main/java/to/bitkit/data/ChatwootHttpClient.kt index e4d505a27..eed4eed8d 100644 --- a/app/src/main/java/to/bitkit/data/ChatwootHttpClient.kt +++ b/app/src/main/java/to/bitkit/data/ChatwootHttpClient.kt @@ -60,5 +60,5 @@ class ChatwootHttpClient @Inject constructor( } sealed class ChatwootHttpError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : ChatwootHttpError(message) + class InvalidResponse(override val message: String) : ChatwootHttpError(message) } diff --git a/app/src/main/java/to/bitkit/data/backup/VssBackupClient.kt b/app/src/main/java/to/bitkit/data/backup/VssBackupClient.kt index f5a6e0a0b..b0b95c95b 100644 --- a/app/src/main/java/to/bitkit/data/backup/VssBackupClient.kt +++ b/app/src/main/java/to/bitkit/data/backup/VssBackupClient.kt @@ -40,7 +40,7 @@ class VssBackupClient @Inject constructor( Logger.verbose("Building VSS client with lnurlAuthServerUrl: '$lnurlAuthServerUrl'") if (lnurlAuthServerUrl.isNotEmpty()) { val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) - ?: throw ServiceError.MnemonicNotFound + ?: throw ServiceError.MnemonicNotFound() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) vssNewClientWithLnurlAuth( diff --git a/app/src/main/java/to/bitkit/data/backup/VssStoreIdProvider.kt b/app/src/main/java/to/bitkit/data/backup/VssStoreIdProvider.kt index a682ed9bc..5f88f13a9 100644 --- a/app/src/main/java/to/bitkit/data/backup/VssStoreIdProvider.kt +++ b/app/src/main/java/to/bitkit/data/backup/VssStoreIdProvider.kt @@ -19,7 +19,8 @@ class VssStoreIdProvider @Inject constructor( synchronized(this) { cacheMap[walletIndex]?.let { return it } - val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound + val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) + ?: throw ServiceError.MnemonicNotFound() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) val storeId = vssDeriveStoreId( diff --git a/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt b/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt index d0695acc8..f2ba871a2 100644 --- a/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt +++ b/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt @@ -101,5 +101,5 @@ class BlocksService @Inject constructor( * Block-specific error types */ sealed class BlockError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : BlockError(message) + class InvalidResponse(override val message: String) : BlockError(message) } diff --git a/app/src/main/java/to/bitkit/data/widgets/NewsService.kt b/app/src/main/java/to/bitkit/data/widgets/NewsService.kt index a04d8f125..108381eb7 100644 --- a/app/src/main/java/to/bitkit/data/widgets/NewsService.kt +++ b/app/src/main/java/to/bitkit/data/widgets/NewsService.kt @@ -52,5 +52,5 @@ class NewsService @Inject constructor( * News-specific error types */ sealed class NewsError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : NewsError(message) + class InvalidResponse(override val message: String) : NewsError(message) } diff --git a/app/src/main/java/to/bitkit/data/widgets/PriceService.kt b/app/src/main/java/to/bitkit/data/widgets/PriceService.kt index 6d11929b4..ced46186c 100644 --- a/app/src/main/java/to/bitkit/data/widgets/PriceService.kt +++ b/app/src/main/java/to/bitkit/data/widgets/PriceService.kt @@ -180,6 +180,6 @@ class PriceService @Inject constructor( * Price-specific error types */ sealed class PriceError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : PriceError(message) - data class NetworkError(override val message: String) : PriceError(message) + class InvalidResponse(override val message: String) : PriceError(message) + class NetworkError(override val message: String) : PriceError(message) } diff --git a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt index aa007bbe3..83107fede 100644 --- a/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt @@ -201,8 +201,8 @@ class BlocktankRepo @Inject constructor( description: String = Env.DEFAULT_INVOICE_MESSAGE, ): Result = withContext(bgDispatcher) { try { - if (coreService.isGeoBlocked()) throw ServiceError.GeoBlocked - val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted + if (coreService.isGeoBlocked()) throw ServiceError.GeoBlocked() + val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted() val lspBalance = getDefaultLspBalance(clientBalance = amountSats) val channelSizeSat = amountSats + lspBalance @@ -230,7 +230,7 @@ class BlocktankRepo @Inject constructor( channelExpiryWeeks: UInt = DEFAULT_CHANNEL_EXPIRY_WEEKS, ): Result = withContext(bgDispatcher) { try { - if (coreService.isGeoBlocked()) throw ServiceError.GeoBlocked + if (coreService.isGeoBlocked()) throw ServiceError.GeoBlocked() val options = defaultCreateOrderOptions(clientBalanceSat = spendingBalanceSats) @@ -323,7 +323,7 @@ class BlocktankRepo @Inject constructor( } private suspend fun defaultCreateOrderOptions(clientBalanceSat: ULong): CreateOrderOptions { - val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted + val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted() val timestamp = nowTimestamp().toString() val signature = lightningService.sign("channelOpen-$timestamp") @@ -350,7 +350,7 @@ class BlocktankRepo @Inject constructor( } val satsPerEur = getSatsPerEur() - ?: throw ServiceError.CurrencyRateUnavailable + ?: throw ServiceError.CurrencyRateUnavailable() val params = DefaultLspBalanceParams( clientBalanceSat = clientBalance, @@ -363,10 +363,10 @@ class BlocktankRepo @Inject constructor( fun calculateLiquidityOptions(clientBalanceSat: ULong): Result { val blocktankInfo = blocktankState.value.info - ?: return Result.failure(ServiceError.BlocktankInfoUnavailable) + ?: return Result.failure(ServiceError.BlocktankInfoUnavailable()) val satsPerEur = getSatsPerEur() - ?: return Result.failure(ServiceError.CurrencyRateUnavailable) + ?: return Result.failure(ServiceError.CurrencyRateUnavailable()) val existingChannelsTotalSat = totalBtChannelsValueSats(blocktankInfo) @@ -466,7 +466,7 @@ class BlocktankRepo @Inject constructor( } private suspend fun claimGiftCodeWithoutLiquidity(code: String, amount: ULong): GiftClaimResult { - val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted + val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted() val order = ServiceQueue.CORE.background { giftOrder(clientNodeId = nodeId, code = "blocktank-gift-code:$code") diff --git a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt index a8241e194..29a5b23cc 100644 --- a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt @@ -628,7 +628,7 @@ class LightningRepo @Inject constructor( callback: String, domain: String, ): Result = runCatching { - val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound + val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) val result = lnurlAuth( diff --git a/app/src/main/java/to/bitkit/repositories/WalletRepo.kt b/app/src/main/java/to/bitkit/repositories/WalletRepo.kt index d46f18eb9..fc5bae3c4 100644 --- a/app/src/main/java/to/bitkit/repositories/WalletRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/WalletRepo.kt @@ -347,7 +347,8 @@ class WalletRepo @Inject constructor( count: Int = 20, ): Result> = withContext(bgDispatcher) { return@withContext try { - val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound + val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) + ?: throw ServiceError.MnemonicNotFound() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) diff --git a/app/src/main/java/to/bitkit/services/AppUpdaterService.kt b/app/src/main/java/to/bitkit/services/AppUpdaterService.kt index 4ab68adae..eedf28331 100644 --- a/app/src/main/java/to/bitkit/services/AppUpdaterService.kt +++ b/app/src/main/java/to/bitkit/services/AppUpdaterService.kt @@ -37,5 +37,5 @@ class AppUpdaterService @Inject constructor( } sealed class AppUpdaterError(message: String) : AppError(message) { - data class InvalidResponse(override val message: String) : AppUpdaterError(message) + class InvalidResponse(override val message: String) : AppUpdaterError(message) } diff --git a/app/src/main/java/to/bitkit/services/CoreService.kt b/app/src/main/java/to/bitkit/services/CoreService.kt index 441357454..a46a354eb 100644 --- a/app/src/main/java/to/bitkit/services/CoreService.kt +++ b/app/src/main/java/to/bitkit/services/CoreService.kt @@ -1387,7 +1387,7 @@ class BlocktankService( } suspend fun open(orderId: String): IBtOrder { - val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted + val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted() val latestOrder = ServiceQueue.CORE.background { getOrders(orderIds = listOf(orderId), filter = null, refresh = true).firstOrNull() diff --git a/app/src/main/java/to/bitkit/services/CurrencyService.kt b/app/src/main/java/to/bitkit/services/CurrencyService.kt index 463db9bd6..7ddee3181 100644 --- a/app/src/main/java/to/bitkit/services/CurrencyService.kt +++ b/app/src/main/java/to/bitkit/services/CurrencyService.kt @@ -33,10 +33,10 @@ class CurrencyService @Inject constructor( } } - throw lastError ?: CurrencyError.Unknown + throw lastError ?: CurrencyError.Unknown() } } sealed class CurrencyError(message: String) : AppError(message) { - data object Unknown : CurrencyError("Unknown error occurred while fetching rates") + class Unknown : CurrencyError("Unknown error occurred while fetching rates") } diff --git a/app/src/main/java/to/bitkit/services/LightningService.kt b/app/src/main/java/to/bitkit/services/LightningService.kt index d7585aff4..2a443a68b 100644 --- a/app/src/main/java/to/bitkit/services/LightningService.kt +++ b/app/src/main/java/to/bitkit/services/LightningService.kt @@ -140,8 +140,10 @@ class LightningService @Inject constructor( ) } + val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) + ?: throw ServiceError.MnemonicNotFound() setEntropyBip39Mnemonic( - mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) ?: throw ServiceError.MnemonicNotFound, + mnemonic = mnemonic, passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name), ) } @@ -193,7 +195,7 @@ class LightningService @Inject constructor( } suspend fun start(timeout: Duration? = null, onEvent: NodeEventHandler? = null) { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.debug("Starting node…", context = TAG) @@ -227,7 +229,7 @@ class LightningService @Inject constructor( suspend fun stop() { shouldListenForEvents = false - val node = this.node ?: throw ServiceError.NodeNotStarted + val node = this.node ?: throw ServiceError.NodeNotStarted() Logger.debug("Stopping node…", context = TAG) ServiceQueue.LDK.background { @@ -243,14 +245,14 @@ class LightningService @Inject constructor( } fun wipeStorage(walletIndex: Int) { - if (node != null) throw ServiceError.NodeStillRunning + if (node != null) throw ServiceError.NodeStillRunning() Logger.warn("Wiping LDK storage…", context = TAG) Path(Env.ldkStoragePath(walletIndex)).toFile().deleteRecursively() Logger.info("LDK storage wiped", context = TAG) } suspend fun sync() { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.verbose("Syncing LDK…", context = TAG) ServiceQueue.LDK.background { @@ -263,8 +265,8 @@ class LightningService @Inject constructor( } suspend fun sign(message: String): String { - val node = this.node ?: throw ServiceError.NodeNotSetup - val msg = runCatching { message.uByteList }.getOrNull() ?: throw ServiceError.InvalidNodeSigningMessage + val node = this.node ?: throw ServiceError.NodeNotSetup() + val msg = runCatching { message.uByteList }.getOrNull() ?: throw ServiceError.InvalidNodeSigningMessage() return ServiceQueue.LDK.background { node.signMessage(msg) @@ -272,7 +274,7 @@ class LightningService @Inject constructor( } suspend fun newAddress(): String { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { node.onchainPayment().newAddress() @@ -281,7 +283,7 @@ class LightningService @Inject constructor( // region peers suspend fun connectToTrustedPeers() { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() ServiceQueue.LDK.background { for (peer in trustedPeers) { @@ -317,7 +319,7 @@ class LightningService @Inject constructor( } suspend fun connectPeer(peer: PeerDetails): Result { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() val uri = peer.uri return ServiceQueue.LDK.background { try { @@ -337,7 +339,7 @@ class LightningService @Inject constructor( } suspend fun disconnectPeer(peer: PeerDetails) { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() val uri = peer.uri Logger.debug("Disconnecting peer: $uri", context = TAG) try { @@ -378,7 +380,7 @@ class LightningService @Inject constructor( pushToCounterpartySats: ULong? = null, channelConfig: ChannelConfig? = null, ): Result { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { try { @@ -418,7 +420,7 @@ class LightningService @Inject constructor( force: Boolean = false, forceCloseReason: String? = null, ) { - val node = this.node ?: throw ServiceError.NodeNotStarted + val node = this.node ?: throw ServiceError.NodeNotStarted() val channelId = channel.channelId val userChannelId = channel.userChannelId val counterpartyNodeId = channel.counterpartyNodeId @@ -463,7 +465,7 @@ class LightningService @Inject constructor( } suspend fun receive(sat: ULong? = null, description: String, expirySecs: UInt = 3600u): String { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() val message = description.ifBlank { Env.DEFAULT_INVOICE_MESSAGE } @@ -511,7 +513,7 @@ class LightningService @Inject constructor( utxosToSpend: List? = null, isMaxAmount: Boolean = false, ): Txid { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.info( "Sending $sats sats to $address, satsPerVByte=$satsPerVByte, isMaxAmount = $isMaxAmount", @@ -537,7 +539,7 @@ class LightningService @Inject constructor( } suspend fun send(bolt11: String, sats: ULong? = null): PaymentId { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.debug("Paying bolt11: $bolt11", context = TAG) @@ -557,7 +559,7 @@ class LightningService @Inject constructor( } suspend fun estimateRoutingFees(bolt11: String): Result { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { return@background try { @@ -574,7 +576,7 @@ class LightningService @Inject constructor( } suspend fun estimateRoutingFeesForAmount(bolt11: String, amountSats: ULong): Result { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { return@background try { @@ -594,7 +596,7 @@ class LightningService @Inject constructor( // region utxo selection suspend fun listSpendableOutputs(): Result> { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { return@background try { @@ -614,7 +616,7 @@ class LightningService @Inject constructor( algorithm: CoinSelectionAlgorithm, utxos: List?, ): Result> { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { return@background try { @@ -636,7 +638,7 @@ class LightningService @Inject constructor( // region boost suspend fun bumpFeeByRbf(txid: Txid, satsPerVByte: ULong): Txid { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.info("RBF for txid='$txid' using satsPerVByte='$satsPerVByte'", context = TAG) @@ -657,7 +659,7 @@ class LightningService @Inject constructor( satsPerVByte: ULong, toAddress: Address, ): Txid { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.info("CPFP for txid='$txid' using satsPerVByte='$satsPerVByte', to address='$toAddress'", context = TAG) @@ -677,7 +679,7 @@ class LightningService @Inject constructor( // region fee suspend fun calculateCpfpFeeRate(parentTxid: Txid): FeeRate { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.debug("Calculating CPFP fee for parentTxid $parentTxid", context = TAG) @@ -699,7 +701,7 @@ class LightningService @Inject constructor( satsPerVByte: ULong, utxosToSpend: List? = null, ): ULong { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() Logger.verbose( "Calculating fee for $amountSats sats to $address, ${utxosToSpend?.size} UTXOs, satsPerVByte=$satsPerVByte", @@ -732,7 +734,7 @@ class LightningService @Inject constructor( suspend fun listenForEvents(onEvent: NodeEventHandler? = null) = withContext(bgDispatcher) { while (shouldListenForEvents) { val node = this@LightningService.node ?: let { - Logger.error(ServiceError.NodeNotStarted.message.orEmpty(), context = TAG) + Logger.error(ServiceError.NodeNotStarted().message.orEmpty(), context = TAG) return@withContext } val event = node.nextEventAsync() @@ -749,7 +751,7 @@ class LightningService @Inject constructor( // endregion suspend fun getAddressBalance(address: String): ULong { - val node = this.node ?: throw ServiceError.NodeNotSetup + val node = this.node ?: throw ServiceError.NodeNotSetup() return ServiceQueue.LDK.background { try { node.getAddressBalance(addressStr = address) @@ -920,7 +922,7 @@ class LightningService @Inject constructor( } suspend fun exportNetworkGraphToFile(outputDir: String): Result { - val node = this.node ?: return Result.failure(ServiceError.NodeNotSetup) + val node = this.node ?: return Result.failure(ServiceError.NodeNotSetup()) return withContext(bgDispatcher) { runCatching { diff --git a/app/src/main/java/to/bitkit/services/LspNotificationsService.kt b/app/src/main/java/to/bitkit/services/LspNotificationsService.kt index 08215384a..955b775d9 100644 --- a/app/src/main/java/to/bitkit/services/LspNotificationsService.kt +++ b/app/src/main/java/to/bitkit/services/LspNotificationsService.kt @@ -24,7 +24,7 @@ class LspNotificationsService @Inject constructor( private val crypto: Crypto, ) { suspend fun registerDevice(deviceToken: String) = withContext(bgDispatcher) { - val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted + val nodeId = lightningService.nodeId ?: throw ServiceError.NodeNotStarted() Logger.debug("Registering device for notifications…") diff --git a/app/src/main/java/to/bitkit/services/RNBackupClient.kt b/app/src/main/java/to/bitkit/services/RNBackupClient.kt index fc1062e6c..1613df269 100644 --- a/app/src/main/java/to/bitkit/services/RNBackupClient.kt +++ b/app/src/main/java/to/bitkit/services/RNBackupClient.kt @@ -59,7 +59,7 @@ class RNBackupClient @Inject constructor( suspend fun listFiles(fileGroup: String? = "ldk"): RNBackupListResponse? = withContext(ioDispatcher) { runCatching { val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) - ?: throw RNBackupError.NotSetup + ?: throw RNBackupError.NotSetup() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) val bearer = authenticate(mnemonic, passphrase) @@ -81,7 +81,7 @@ class RNBackupClient @Inject constructor( suspend fun retrieve(label: String, fileGroup: String? = null): ByteArray? = withContext(ioDispatcher) { runCatching { val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) - ?: throw RNBackupError.NotSetup + ?: throw RNBackupError.NotSetup() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) val bearer = authenticate(mnemonic, passphrase) @@ -109,7 +109,7 @@ class RNBackupClient @Inject constructor( suspend fun retrieveChannelMonitor(channelId: String): ByteArray? = withContext(ioDispatcher) { runCatching { val mnemonic = keychain.loadString(Keychain.Key.BIP39_MNEMONIC.name) - ?: throw RNBackupError.NotSetup + ?: throw RNBackupError.NotSetup() val passphrase = keychain.loadString(Keychain.Key.BIP39_PASSPHRASE.name) val bearer = authenticate(mnemonic, passphrase) @@ -236,7 +236,7 @@ class RNBackupClient @Inject constructor( } if (!challengeResponse.status.isSuccess()) { - throw RNBackupError.AuthFailed + throw RNBackupError.AuthFailed() } val challengeResult = challengeResponse.body() @@ -254,7 +254,7 @@ class RNBackupClient @Inject constructor( } if (!authResponse.status.isSuccess()) { - throw RNBackupError.AuthFailed + throw RNBackupError.AuthFailed() } authResponse.body().also { cachedBearer = it } @@ -355,8 +355,8 @@ data class RNBackupListResponse( ) sealed class RNBackupError(message: String) : AppError(message) { - data object NotSetup : RNBackupError("RN backup client not setup") - data object AuthFailed : RNBackupError("Authentication failed") - data class RequestFailed(override val message: String) : RNBackupError(message) - data class DecryptFailed(override val message: String) : RNBackupError(message) + class NotSetup : RNBackupError("RN backup client not setup") + class AuthFailed : RNBackupError("Authentication failed") + class RequestFailed(override val message: String) : RNBackupError(message) + class DecryptFailed(override val message: String) : RNBackupError(message) } diff --git a/app/src/main/java/to/bitkit/utils/Crypto.kt b/app/src/main/java/to/bitkit/utils/Crypto.kt index dbce66c8e..d040500ff 100644 --- a/app/src/main/java/to/bitkit/utils/Crypto.kt +++ b/app/src/main/java/to/bitkit/utils/Crypto.kt @@ -61,7 +61,7 @@ class Crypto @Inject constructor() { } } } catch (e: Exception) { - throw CryptoError.SecurityProviderSetupFailed + throw CryptoError.SecurityProviderSetupFailed() } } @@ -80,7 +80,7 @@ class Crypto @Inject constructor() { publicKey = publicKey, ) } catch (e: Exception) { - throw CryptoError.KeypairGenerationFailed + throw CryptoError.KeypairGenerationFailed() } } @@ -111,7 +111,7 @@ class Crypto @Inject constructor() { return baseSecret } catch (e: Exception) { - throw CryptoError.SharedSecretGenerationFailed + throw CryptoError.SharedSecretGenerationFailed() } } @@ -139,7 +139,7 @@ class Crypto @Inject constructor() { return cipher.doFinal(encryptedPayload.cipher + encryptedPayload.tag) } catch (e: Exception) { - throw CryptoError.DecryptionFailed + throw CryptoError.DecryptionFailed() } } @@ -171,7 +171,7 @@ class Crypto @Inject constructor() { val recId = calculateRecoveryId(r, s, messageHash, privateKeyBigInt, curve) formatSignature(recId, r, s) } - }.getOrElse { throw CryptoError.SigningFailed } + }.getOrElse { throw CryptoError.SigningFailed() } fun getPublicKey(privateKey: ByteArray): ByteArray = runCatching { val keyFactory = KeyFactory.getInstance("EC", "BC") @@ -180,7 +180,7 @@ class Crypto @Inject constructor() { val publicKeyPoint = params.g.multiply((privateKeyObj as ECPrivateKey).d) publicKeyPoint.getEncoded(true) - }.getOrElse { throw CryptoError.PublicKeyCreationFailed } + }.getOrElse { throw CryptoError.PublicKeyCreationFailed() } private fun calculateRecoveryId( r: BigInteger, @@ -214,7 +214,7 @@ class Crypto @Inject constructor() { continue } } - throw CryptoError.SigningFailed + throw CryptoError.SigningFailed() } private fun formatSignature(recId: Int, r: BigInteger, s: BigInteger): String { @@ -231,10 +231,10 @@ class Crypto @Inject constructor() { } sealed class CryptoError(message: String) : AppError(message) { - data object SharedSecretGenerationFailed : CryptoError("Shared secret generation failed") - data object SecurityProviderSetupFailed : CryptoError("Security provider setup failed") - data object KeypairGenerationFailed : CryptoError("Keypair generation failed") - data object DecryptionFailed : CryptoError("Decryption failed") - data object SigningFailed : CryptoError("Signing failed") - data object PublicKeyCreationFailed : CryptoError("Public key creation failed") + class SharedSecretGenerationFailed : CryptoError("Shared secret generation failed") + class SecurityProviderSetupFailed : CryptoError("Security provider setup failed") + class KeypairGenerationFailed : CryptoError("Keypair generation failed") + class DecryptionFailed : CryptoError("Decryption failed") + class SigningFailed : CryptoError("Signing failed") + class PublicKeyCreationFailed : CryptoError("Public key creation failed") } diff --git a/app/src/main/java/to/bitkit/utils/Errors.kt b/app/src/main/java/to/bitkit/utils/Errors.kt index 9796db4bf..8855617fd 100644 --- a/app/src/main/java/to/bitkit/utils/Errors.kt +++ b/app/src/main/java/to/bitkit/utils/Errors.kt @@ -5,33 +5,17 @@ package to.bitkit.utils import org.lightningdevkit.ldknode.BuildException import org.lightningdevkit.ldknode.NodeException -// TODO add cause as inner exception -open class AppError(override val message: String? = null) : Exception(message) { - companion object { - @Suppress("ConstPropertyName") - private const val serialVersionUID = 1L - } - - constructor(cause: Throwable) : this("${cause::class.simpleName}='${cause.message}'") - - fun readResolve(): Any { - // Return a new instance of the class, or handle it if needed - return this - } -} +open class AppError(override val message: String? = null) : Exception(message) sealed class ServiceError(message: String) : AppError(message) { - data object NodeNotSetup : ServiceError("Node is not setup") - data object NodeNotStarted : ServiceError("Node is not started") - data object NodeStartTimeout : ServiceError("Node took too long to start") - class LdkNodeSqliteAlreadyExists(path: String) : ServiceError("LDK-node SQLite file already exists at $path") - data object LdkToLdkNodeMigration : ServiceError("LDK to LDK-node migration issue") - data object MnemonicNotFound : ServiceError("Mnemonic not found") - data object NodeStillRunning : ServiceError("Node is still running") - data object InvalidNodeSigningMessage : ServiceError("Invalid node signing message") - data object CurrencyRateUnavailable : ServiceError("Currency rate unavailable") - data object BlocktankInfoUnavailable : ServiceError("Blocktank info not available") - data object GeoBlocked : ServiceError("Geo blocked user") + class NodeNotSetup : ServiceError("Node is not setup") + class NodeNotStarted : ServiceError("Node is not started") + class MnemonicNotFound : ServiceError("Mnemonic not found") + class NodeStillRunning : ServiceError("Node is still running") + class InvalidNodeSigningMessage : ServiceError("Invalid node signing message") + class CurrencyRateUnavailable : ServiceError("Currency rate unavailable") + class BlocktankInfoUnavailable : ServiceError("Blocktank info not available") + class GeoBlocked : ServiceError("Geo blocked user") } // region ldk @@ -129,6 +113,4 @@ class LdkError(private val inner: LdkException) : AppError("Unknown LDK error.") } // endregion -/** Check if the throwable is a TxSyncTimeout exception. */ -fun Throwable.isTxSyncTimeout(): Boolean = - this is NodeException.TxSyncTimeout || cause is NodeException.TxSyncTimeout +fun Throwable.isTxSyncTimeout(): Boolean = this is NodeException.TxSyncTimeout || cause is NodeException.TxSyncTimeout