From 943baed9b83de8f80b555b034b3b3933aed6a224 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 20 Apr 2026 12:38:40 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../DefaultDynamicAddressesRepository.kt | 8 +-- .../DefaultWalletManagersFacade.kt | 49 ++++++++++++------- .../walletmanager/WalletManagersFacade.kt | 2 + 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/data/dynamic-addresses/src/main/java/com/tangem/data/dynamicaddresses/DefaultDynamicAddressesRepository.kt b/data/dynamic-addresses/src/main/java/com/tangem/data/dynamicaddresses/DefaultDynamicAddressesRepository.kt index 1830d9415f..9f36682a75 100644 --- a/data/dynamic-addresses/src/main/java/com/tangem/data/dynamicaddresses/DefaultDynamicAddressesRepository.kt +++ b/data/dynamic-addresses/src/main/java/com/tangem/data/dynamicaddresses/DefaultDynamicAddressesRepository.kt @@ -34,7 +34,8 @@ internal class DefaultDynamicAddressesRepository( val token = response.findToken(network) when { token?.dynamicAddressesEnabled != true -> DynamicAddressesStatus.DISABLED - !isXpubAvailable(userWalletId, network) -> DynamicAddressesStatus.ENABLED_REQUIRES_SETUP + !walletManagersFacade.isDynamicAddressesEnabled(userWalletId, network) -> + DynamicAddressesStatus.ENABLED_REQUIRES_SETUP else -> DynamicAddressesStatus.ENABLED } } @@ -145,11 +146,6 @@ internal class DefaultDynamicAddressesRepository( } } - private suspend fun isXpubAvailable(userWalletId: UserWalletId, network: Network): Boolean { - // Check if WalletManager is already in XPUB mode (dynamic addresses were previously enabled on this device) - return walletManagersFacade.getDynamicAddressesReceiveAddress(userWalletId, network) != null - } - private fun GetWalletAccountsResponse.findToken(network: Network): UserTokensResponse.Token? { return accounts .flatMap { it.tokens.orEmpty() } diff --git a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt index c23bb4c58e..3401f5d920 100644 --- a/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt +++ b/data/wallet-manager/src/main/java/com/tangem/data/walletmanager/DefaultWalletManagersFacade.kt @@ -209,11 +209,14 @@ internal class DefaultWalletManagersFacade @Inject constructor( "Unable to get a wallet manager for blockchain: $blockchain" } - val address = walletManager - .wallet - .addresses - .find { it.type == addressType } - ?.value ?: walletManager.wallet.address + val isDynamicAddressesEnabled = (walletManager as? DynamicAddressesManager)?.isDynamicAddressesEnabled == true + + val address = if (isDynamicAddressesEnabled) { + getDynamicAddressesLastUsedReceiveAddress(userWalletId, network) ?: walletManager.wallet.address + } else { + walletManager.wallet.addresses.find { it.type == addressType }?.value ?: walletManager.wallet.address + } + return blockchain.getExploreUrl(address, contractAddress) } @@ -466,9 +469,12 @@ internal class DefaultWalletManagersFacade @Inject constructor( } } + override suspend fun isDynamicAddressesEnabled(userWalletId: UserWalletId, network: Network): Boolean { + return getEnabledDynamicAddressesManagerOrNull(userWalletId, network) != null + } + override suspend fun getDynamicAddressesReceiveAddress(userWalletId: UserWalletId, network: Network): String? { - val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = network) - val dynamicAddressesManager = walletManager as? DynamicAddressesManager ?: return null + val dynamicAddressesManager = getEnabledDynamicAddressesManagerOrNull(userWalletId, network) ?: return null return dynamicAddressesManager.findFirstUnusedReceiveAddress()?.address } @@ -476,23 +482,21 @@ internal class DefaultWalletManagersFacade @Inject constructor( userWalletId: UserWalletId, network: Network, ): String? { - val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = network) - val dynamicAddressesManager = walletManager as? DynamicAddressesManager ?: return null + val dynamicAddressesManager = getEnabledDynamicAddressesManagerOrNull(userWalletId, network) ?: return null return dynamicAddressesManager.usedAddresses - .filter { usedAddress -> + .mapNotNull { usedAddress -> val nodes = runCatching { DerivationPath(usedAddress.derivationPath).nodes }.getOrNull() - ?: return@filter false - nodes.size >= XPUB_PATH_MIN_NODES && nodes[nodes.size - 2].index == RECEIVE_CHAIN_INDEX + ?: return@mapNotNull null + if (nodes.size < XPUB_PATH_MIN_NODES) return@mapNotNull null + if (nodes[nodes.size - 2].index != RECEIVE_CHAIN_INDEX) return@mapNotNull null + usedAddress to nodes.last().index } - .maxByOrNull { usedAddress -> - runCatching { DerivationPath(usedAddress.derivationPath).nodes.last().index }.getOrDefault(0L) - } - ?.address + .maxByOrNull { (_, lastIndex) -> lastIndex } + ?.first?.address } override suspend fun hasDynamicAddressesNonBaseBalances(userWalletId: UserWalletId, network: Network): Boolean { - val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = network) - val dynamicAddressesManager = walletManager as? DynamicAddressesManager ?: return false + val dynamicAddressesManager = getEnabledDynamicAddressesManagerOrNull(userWalletId, network) ?: return false return dynamicAddressesManager.usedAddresses.any { usedAddress -> val nodes = runCatching { DerivationPath(usedAddress.derivationPath).nodes }.getOrNull() ?: return@any false @@ -503,8 +507,17 @@ internal class DefaultWalletManagersFacade @Inject constructor( } } + private suspend fun getEnabledDynamicAddressesManagerOrNull( + userWalletId: UserWalletId, + network: Network, + ): DynamicAddressesManager? { + val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = network) + return (walletManager as? DynamicAddressesManager)?.takeIf { it.isDynamicAddressesEnabled } + } + private fun restoreXpubModeIfNeeded(walletManager: WalletManager, xpub: String) { val dynamicAddressesManager = walletManager as? DynamicAddressesManager ?: return + if (dynamicAddressesManager.isDynamicAddressesEnabled) return try { dynamicAddressesManager.enableDynamicAddresses(xpub) diff --git a/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt b/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt index 92824ca373..854c807db6 100644 --- a/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt +++ b/domain/wallet-manager/src/main/kotlin/com/tangem/domain/walletmanager/WalletManagersFacade.kt @@ -295,6 +295,8 @@ interface WalletManagersFacade { suspend fun disableXpubMode(userWalletId: UserWalletId, network: Network): SimpleResult + suspend fun isDynamicAddressesEnabled(userWalletId: UserWalletId, network: Network): Boolean + suspend fun getDynamicAddressesReceiveAddress(userWalletId: UserWalletId, network: Network): String? suspend fun getDynamicAddressesLastUsedReceiveAddress(userWalletId: UserWalletId, network: Network): String?