diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index c3092a3714..33a23f9750 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -14,6 +14,7 @@ import com.tangem.domain.common.extensions.toNetworkId import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.Network +import com.tangem.domain.tokens.model.NetworkAddress import com.tangem.feature.swap.presentation.SwapFragment import com.tangem.features.send.api.navigation.SendRouter import com.tangem.tap.common.analytics.events.AnalyticsParam @@ -123,7 +124,10 @@ class TradeCryptoMiddleware { } private fun proceedNewBuyAction(state: () -> AppState?, action: TradeCryptoAction.New.Buy) { - val networkAddress = action.cryptoCurrencyStatus.value.networkAddress?.defaultAddress ?: return + val networkAddress = action.cryptoCurrencyStatus.value.networkAddress + ?.defaultAddress + ?.let(NetworkAddress.Address::value) + ?: return val status = action.cryptoCurrencyStatus val currency = status.currency @@ -206,7 +210,10 @@ class TradeCryptoMiddleware { } private fun proceedNewSellAction(action: TradeCryptoAction.New.Sell) { - val networkAddress = action.cryptoCurrencyStatus.value.networkAddress?.defaultAddress ?: return + val networkAddress = action.cryptoCurrencyStatus.value.networkAddress + ?.defaultAddress + ?.let(NetworkAddress.Address::value) + ?: return val currency = action.cryptoCurrencyStatus.currency store.state.globalState.exchangeManager.getUrl( diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/chooseaddress/ChooseAddressBottomSheet.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/chooseaddress/ChooseAddressBottomSheet.kt index 4bec68b142..098950828e 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/chooseaddress/ChooseAddressBottomSheet.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/chooseaddress/ChooseAddressBottomSheet.kt @@ -8,6 +8,7 @@ import com.tangem.core.ui.R import com.tangem.core.ui.components.SimpleSettingsRow import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig +import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.res.TangemTheme @Composable @@ -24,7 +25,7 @@ private fun ChooseAddressBottomSheetContent(content: ChooseAddressBottomSheetCon ) { content.addressModels.forEach { addressModel -> SimpleSettingsRow( - title = addressModel.type.name, + title = addressModel.displayName.resolveReference(), icon = R.drawable.ic_arrow_top_right_24, onItemsClick = { content.onClick(addressModel) }, ) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressMappers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressMappers.kt new file mode 100644 index 0000000000..dfd23f44c2 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressMappers.kt @@ -0,0 +1,43 @@ +package com.tangem.core.ui.components.bottomsheets.tokenreceive + +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.domain.tokens.model.CryptoCurrency +import com.tangem.domain.tokens.model.Network +import com.tangem.domain.tokens.model.NetworkAddress + +private const val DSC_ADDRESS_NAME = "DSC" +private const val DEL_ADDRESS_NAME = "Main" + +private const val LEGACY_ADDRESS_NAME = "Legacy" +private const val DEFAULT_ADDRESS_NAME = "Default" + +fun Set.mapToAddressModels(currency: CryptoCurrency): List = this + .sortedBy { it.type.ordinal } + .map { address -> + AddressModel( + displayName = currency.network.getAddressDisplayName(address.type), + value = address.value, + type = when (address.type) { + NetworkAddress.Address.Type.Primary -> AddressModel.Type.Default + NetworkAddress.Address.Type.Secondary -> AddressModel.Type.Legacy + }, + ) + } + +private fun Network.getAddressDisplayName(addressType: NetworkAddress.Address.Type): TextReference { + return when (id.value) { + "decimal", "decimal/test" -> { + when (addressType) { + NetworkAddress.Address.Type.Primary -> stringReference(value = DEL_ADDRESS_NAME) + NetworkAddress.Address.Type.Secondary -> stringReference(value = DSC_ADDRESS_NAME) + } + } + else -> { + when (addressType) { + NetworkAddress.Address.Type.Primary -> stringReference(value = DEFAULT_ADDRESS_NAME) + NetworkAddress.Address.Type.Secondary -> stringReference(value = LEGACY_ADDRESS_NAME) + } + } + } +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressModel.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressModel.kt index 0314b21846..8571fdfa35 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressModel.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/AddressModel.kt @@ -1,8 +1,11 @@ package com.tangem.core.ui.components.bottomsheets.tokenreceive +import com.tangem.core.ui.extensions.TextReference + data class AddressModel( + val displayName: TextReference, val value: String, - val type: Type = Type.Default, + val type: Type, ) { enum class Type { Legacy, Default diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt index 704418b5ec..1057a43847 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheet.kt @@ -9,7 +9,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.* +import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -26,6 +26,7 @@ import com.tangem.core.ui.components.SecondaryButtonIconStart import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.rememberQrPainters +import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.shareText import com.tangem.core.ui.res.TangemTheme @@ -181,13 +182,6 @@ private fun getName(content: TokenReceiveBottomSheetConfig, index: Int): String return if (content.addresses.size < 2) { content.name } else { - "${ - stringResource( - id = when (content.addresses[index].type) { - AddressModel.Type.Default -> R.string.address_type_default - AddressModel.Type.Legacy -> R.string.address_type_legacy - }, - ) - } ${content.name}" + "${content.addresses[index].displayName.resolveReference()} ${content.name}" } } \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt index c2531a839d..a0a649302c 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/bottomsheets/tokenreceive/TokenReceiveBottomSheetConfig.kt @@ -1,12 +1,13 @@ package com.tangem.core.ui.components.bottomsheets.tokenreceive import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent +import kotlinx.collections.immutable.ImmutableList class TokenReceiveBottomSheetConfig( val name: String, val symbol: String, val network: String, - val addresses: List, + val addresses: ImmutableList, val onCopyClick: () -> Unit, val onShareClick: () -> Unit, ) : TangemBottomSheetConfigContent \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt index e418da8ea3..95a8e5e94e 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/extensions/BlockchainIcons.kt @@ -28,7 +28,6 @@ fun getActiveIconRes(blockchainId: String): Int { "GNO" -> R.drawable.img_gnosis_22 "ETH-Pow", "ETH-Pow/test" -> R.drawable.img_eth_pow_22 "ETH-Fair" -> R.drawable.img_eth_fair_22 - "NEAR", "NEAR/test" -> R.drawable.img_near_22 "Polkadot", "Polkadot/test" -> R.drawable.img_polkadot_22 "Kusama" -> R.drawable.img_kusama_22 "OPTIMISM", "OPTIMISM/test" -> R.drawable.img_optimism_22 diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt index 47979ec3a4..dbbf3fb10a 100644 --- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt +++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/utils/NetworkStatusFactory.kt @@ -2,6 +2,7 @@ package com.tangem.data.tokens.utils import com.tangem.domain.tokens.model.* import com.tangem.domain.txhistory.models.TxHistoryItem +import com.tangem.domain.walletmanager.model.Address import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult @@ -20,12 +21,12 @@ internal class NetworkStatusFactory { is UpdateWalletManagerResult.MissedDerivation -> NetworkStatus.MissedDerivation is UpdateWalletManagerResult.Unreachable -> NetworkStatus.Unreachable is UpdateWalletManagerResult.NoAccount -> NetworkStatus.NoAccount( - address = getNetworkAddress(result.defaultAddress, result.addresses), + address = getNetworkAddress(result.selectedAddress, result.addresses), amountToCreateAccount = result.amountToCreateAccount, errorMessage = result.errorMessage, ) is UpdateWalletManagerResult.Verified -> NetworkStatus.Verified( - address = getNetworkAddress(result.defaultAddress, result.addresses), + address = getNetworkAddress(result.selectedAddress, result.addresses), amounts = formatAmounts(result.currenciesAmounts, currencies), pendingTransactions = formatTransactions( transactions = result.currentTransactions, @@ -92,11 +93,26 @@ internal class NetworkStatusFactory { return transactions.mapTo(hashSetOf()) { it.txHistoryItem } } - private fun getNetworkAddress(defaultAddress: String, availableAddresses: Set): NetworkAddress { + private fun getNetworkAddress(selectedAddress: String, availableAddresses: Set
): NetworkAddress { + val defaultAddress = availableAddresses + .firstOrNull { it.value == selectedAddress } + ?.let(::mapToDomainAddress) + + requireNotNull(defaultAddress) { "Selected address must not be null" } + return if (availableAddresses.size != 1) { - NetworkAddress.Selectable(defaultAddress, availableAddresses) + NetworkAddress.Selectable(defaultAddress, availableAddresses.mapTo(hashSetOf(), ::mapToDomainAddress)) } else { NetworkAddress.Single(defaultAddress) } } + + private fun mapToDomainAddress(address: Address): NetworkAddress.Address { + val type = when (address.type) { + Address.Type.Primary -> NetworkAddress.Address.Type.Primary + Address.Type.Secondary -> NetworkAddress.Address.Type.Secondary + } + + return NetworkAddress.Address(address.value, type) + } } \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt index 2e72d3e67f..e4fb4f23a1 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/extensions/Blockchain.kt @@ -195,8 +195,7 @@ fun Blockchain.toCoinId(): String { Blockchain.Chia, Blockchain.ChiaTestnet -> "chia" Blockchain.Near -> "near" Blockchain.NearTestnet -> "near/test" - Blockchain.Decimal -> "decimal" - Blockchain.DecimalTestnet -> "decimal/test" + Blockchain.Decimal, Blockchain.DecimalTestnet -> "decimal" Blockchain.Unknown -> "unknown" } } @@ -224,6 +223,4 @@ private const val NODL_AMOUNT_TO_CREATE_ACCOUNT = 1.5 private val excludedBlockchains = listOf( Blockchain.Unknown, Blockchain.Ducatus, - Blockchain.Decimal, - Blockchain.DecimalTestnet, ) \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt index 8e830e0bdd..8794d460f7 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt @@ -115,6 +115,7 @@ interface WalletManagersFacade { * @param userWalletId selected wallet id * @param network network of currency */ + @Deprecated("Use NetworkAddress from CryptoCurrencyStatus") suspend fun getAddress(userWalletId: UserWalletId, network: Network): List
/** Returns list of all addresses for all currencies in selected wallet @@ -122,6 +123,7 @@ interface WalletManagersFacade { * @param userWalletId selected wallet id * @param network required to create wallet manager */ + @Deprecated("Use NetworkAddress from CryptoCurrencyStatus") suspend fun getAddresses(userWalletId: UserWalletId, network: Network): Set
/** @@ -155,6 +157,7 @@ interface WalletManagersFacade { * @param userWalletId selected wallet id * @param network network of currency */ + @Deprecated("Will be removed in future") suspend fun getFee( amount: Amount, destination: String, diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/Address.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/Address.kt new file mode 100644 index 0000000000..c495bf7c9a --- /dev/null +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/Address.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.walletmanager.model + +data class Address( + val value: String, + val type: Type, +) { + + enum class Type { + Primary, Secondary, + } +} \ No newline at end of file diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/UpdateWalletManagerResult.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/UpdateWalletManagerResult.kt index ae14d752e1..dd1891105e 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/UpdateWalletManagerResult.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/model/UpdateWalletManagerResult.kt @@ -9,15 +9,15 @@ sealed class UpdateWalletManagerResult { object Unreachable : UpdateWalletManagerResult() data class Verified( - val defaultAddress: String, - val addresses: Set, + val selectedAddress: String, + val addresses: Set
, val currenciesAmounts: Set, val currentTransactions: Set, ) : UpdateWalletManagerResult() data class NoAccount( - val defaultAddress: String, - val addresses: Set, + val selectedAddress: String, + val addresses: Set
, val amountToCreateAccount: BigDecimal, val errorMessage: String, ) : UpdateWalletManagerResult() diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt index 1e9c032f6c..4a67053404 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/utils/UpdateWalletManagerResultFactory.kt @@ -1,15 +1,17 @@ package com.tangem.domain.walletmanager.utils import com.tangem.blockchain.common.* -import com.tangem.blockchain.common.address.Address +import com.tangem.blockchain.common.address.AddressType import com.tangem.domain.common.extensions.amountToCreateAccount import com.tangem.domain.txhistory.models.TxHistoryItem +import com.tangem.domain.walletmanager.model.Address import com.tangem.domain.walletmanager.model.CryptoCurrencyAmount import com.tangem.domain.walletmanager.model.CryptoCurrencyTransaction import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult import timber.log.Timber import java.math.BigDecimal import java.util.concurrent.TimeUnit +import com.tangem.blockchain.common.address.Address as SdkAddress internal class UpdateWalletManagerResultFactory { @@ -18,7 +20,7 @@ internal class UpdateWalletManagerResultFactory { val addresses = getAvailableAddresses(wallet.addresses) return UpdateWalletManagerResult.Verified( - defaultAddress = wallet.address, + selectedAddress = wallet.address, addresses = addresses, currenciesAmounts = getTokensAmounts(wallet.amounts.values.toSet()), currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()), @@ -30,7 +32,7 @@ internal class UpdateWalletManagerResultFactory { val addresses = getAvailableAddresses(wallet.addresses) return UpdateWalletManagerResult.Verified( - defaultAddress = wallet.address, + selectedAddress = wallet.address, addresses = addresses, currenciesAmounts = getDemoTokensAmounts(demoAmount, walletManager.cardTokens), currentTransactions = getCurrentTransactions(addresses, wallet.recentTransactions.toSet()), @@ -48,7 +50,7 @@ internal class UpdateWalletManagerResultFactory { UpdateWalletManagerResult.Unreachable } else { UpdateWalletManagerResult.NoAccount( - defaultAddress = wallet.address, + selectedAddress = wallet.address, addresses = getAvailableAddresses(wallet.addresses), amountToCreateAccount = amountToCreateAccount, errorMessage = customMessage, @@ -70,7 +72,7 @@ internal class UpdateWalletManagerResultFactory { } private fun getCurrentTransactions( - walletAddresses: Set, + walletAddresses: Set
, recentTransactions: Set, ): Set { val unconfirmedTransactions = recentTransactions.filter { @@ -95,7 +97,7 @@ internal class UpdateWalletManagerResultFactory { } private fun createCurrencyTransaction( - walletAddresses: Set, + walletAddresses: Set
, data: TransactionData, ): CryptoCurrencyTransaction? { return when (val type = data.amount.type) { @@ -115,11 +117,11 @@ internal class UpdateWalletManagerResultFactory { } } - private fun createTxHistoryItem(walletAddresses: Set, data: TransactionData): TxHistoryItem? { + private fun createTxHistoryItem(walletAddresses: Set
, data: TransactionData): TxHistoryItem? { val hash = data.hash ?: return null val millis = data.date?.timeInMillis ?: return null val amount = getTransactionAmountValue(data.amount) ?: return null - val isOutgoing = data.sourceAddress in walletAddresses + val isOutgoing = data.sourceAddress in walletAddresses.map { it.value } return TxHistoryItem( txHash = hash, @@ -141,8 +143,16 @@ internal class UpdateWalletManagerResultFactory { ) } - private fun getAvailableAddresses(addresses: Set
): Set { - return addresses.mapTo(hashSetOf()) { it.value } + private fun getAvailableAddresses(addresses: Set): Set
{ + return addresses.mapTo(hashSetOf()) { sdkAddress -> + Address( + value = sdkAddress.value, + type = when (sdkAddress.type) { + AddressType.Default -> Address.Type.Primary + AddressType.Legacy -> Address.Type.Secondary + }, + ) + } } private fun getCurrencyAmountValue(amount: Amount): BigDecimal? { diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt index 5ba1af68eb..23700e3d7b 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/CryptoCurrencyStatus.kt @@ -78,7 +78,7 @@ data class CryptoCurrencyStatus( override val fiatAmount: BigDecimal?, override val priceChange: BigDecimal?, override val fiatRate: BigDecimal?, - override val networkAddress: NetworkAddress?, + override val networkAddress: NetworkAddress, ) : Status(isError = false) { override val amount: BigDecimal = BigDecimal.ZERO @@ -102,7 +102,7 @@ data class CryptoCurrencyStatus( override val priceChange: BigDecimal, override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, - override val networkAddress: NetworkAddress?, + override val networkAddress: NetworkAddress, ) : Status(isError = false) /** @@ -123,7 +123,7 @@ data class CryptoCurrencyStatus( override val priceChange: BigDecimal?, override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, - override val networkAddress: NetworkAddress?, + override val networkAddress: NetworkAddress, ) : Status(isError = false) /** @@ -138,6 +138,6 @@ data class CryptoCurrencyStatus( override val amount: BigDecimal, override val hasCurrentNetworkTransactions: Boolean, override val pendingTransactions: Set, - override val networkAddress: NetworkAddress?, + override val networkAddress: NetworkAddress, ) : Status(isError = false) } \ No newline at end of file diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkAddress.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkAddress.kt index 542d48485e..70d50581d4 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkAddress.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/NetworkAddress.kt @@ -6,18 +6,19 @@ package com.tangem.domain.tokens.model sealed class NetworkAddress { /** The default or currently selected network address. */ - abstract val defaultAddress: String + abstract val defaultAddress: Address + + /** The set of available network addresses to choose from. */ + abstract val availableAddresses: Set
/** * Represents a single static network address. * * @property defaultAddress The static network address. */ - data class Single(override val defaultAddress: String) : NetworkAddress() { + data class Single(override val defaultAddress: Address) : NetworkAddress() { - init { - checkDefaultAddress() - } + override val availableAddresses: Set
= setOf(defaultAddress) } /** @@ -27,17 +28,26 @@ sealed class NetworkAddress { * @property availableAddresses The set of available network addresses to choose from. */ data class Selectable( - override val defaultAddress: String, - val availableAddresses: Set, + override val defaultAddress: Address, + override val availableAddresses: Set
, ) : NetworkAddress() { init { - checkDefaultAddress() require(availableAddresses.isNotEmpty()) { "Available network addresses must not be empty" } } } - protected fun checkDefaultAddress() { - require(defaultAddress.isNotBlank()) { "Selected network address must not be blank" } + data class Address( + val value: String, + val type: Type, + ) { + + enum class Type { + Primary, Secondary, + } + + init { + require(value.isNotBlank()) { "Address value must not be blank" } + } } } \ No newline at end of file diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt index 6cdc76877c..b5c027ac68 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/GetPrimaryCurrencyStatusUpdatesUseCaseTest.kt @@ -118,7 +118,9 @@ internal class GetPrimaryCurrencyStatusUpdatesUseCaseTest { amount = BigDecimal.TEN, hasCurrentNetworkTransactions = false, pendingTransactions = emptySet(), - networkAddress = NetworkAddress.Single(defaultAddress = "mock"), + networkAddress = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) } diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt index 979479e010..369bb8b5b3 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockNetworks.kt @@ -51,7 +51,9 @@ internal object MockNetworks { network = network3, value = NetworkStatus.NoAccount( amountToCreateAccount = amountToCreateAccount, - address = NetworkAddress.Single(defaultAddress = "mock"), + address = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), errorMessage = "", ), ) @@ -67,7 +69,9 @@ internal object MockNetworks { MockTokens.token3.id to CryptoCurrencyAmountStatus.Loaded(BigDecimal.TEN), ), pendingTransactions = emptyMap(), - address = NetworkAddress.Single(defaultAddress = "mock"), + address = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) @@ -80,7 +84,9 @@ internal object MockNetworks { MockTokens.token6.id to CryptoCurrencyAmountStatus.Loaded(BigDecimal.TEN), ), pendingTransactions = emptyMap(), - address = NetworkAddress.Single(defaultAddress = "mock"), + address = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) @@ -94,7 +100,9 @@ internal object MockNetworks { MockTokens.token10.id to CryptoCurrencyAmountStatus.Loaded(BigDecimal.TEN), ), pendingTransactions = emptyMap(), - address = NetworkAddress.Single(defaultAddress = "mock"), + address = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt index 38338ba598..bb9071f999 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/mock/MockTokensStates.kt @@ -3,6 +3,7 @@ package com.tangem.domain.tokens.mock import arrow.core.nonEmptyListOf import com.tangem.domain.tokens.model.CryptoCurrencyAmountStatus import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.NetworkAddress import com.tangem.domain.tokens.model.NetworkStatus import java.math.BigDecimal @@ -64,7 +65,9 @@ internal object MockTokensStates { priceChange = MockQuotes.quote7.priceChange, fiatRate = MockQuotes.quote7.fiatRate, amountToCreateAccount = MockNetworks.amountToCreateAccount, - networkAddress = null, + networkAddress = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) @@ -75,7 +78,9 @@ internal object MockTokensStates { priceChange = MockQuotes.quote8.priceChange, fiatRate = MockQuotes.quote8.fiatRate, amountToCreateAccount = MockNetworks.amountToCreateAccount, - networkAddress = null, + networkAddress = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) @@ -86,7 +91,9 @@ internal object MockTokensStates { priceChange = MockQuotes.quote9.priceChange, fiatRate = MockQuotes.quote9.fiatRate, amountToCreateAccount = MockNetworks.amountToCreateAccount, - networkAddress = null, + networkAddress = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) @@ -97,7 +104,9 @@ internal object MockTokensStates { priceChange = MockQuotes.quote10.priceChange, fiatRate = MockQuotes.quote10.fiatRate, amountToCreateAccount = MockNetworks.amountToCreateAccount, - networkAddress = null, + networkAddress = NetworkAddress.Single( + defaultAddress = NetworkAddress.Address(value = "mock", NetworkAddress.Address.Type.Primary), + ), ), ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index 1494ed003f..997a6e985a 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -2,12 +2,11 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory import androidx.paging.PagingData import arrow.core.Either -import com.tangem.blockchain.common.address.Address import com.tangem.common.Provider import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheetConfig -import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.tokenreceive.mapToAddressModels import com.tangem.core.ui.components.transactions.state.TransactionState import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.event.consumedEvent @@ -17,6 +16,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.NetworkAddress import com.tangem.domain.tokens.model.TokenActionsState import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning import com.tangem.domain.txhistory.models.TxHistoryItem @@ -174,7 +174,7 @@ internal class TokenDetailsStateFactory( fun getStateWithReceiveBottomSheet( currency: CryptoCurrency, - addresses: List
, + networkAddress: NetworkAddress, sendCopyAnalyticsEvent: () -> Unit, sendShareAnalyticsEvent: () -> Unit, ): TokenDetailsState { @@ -186,12 +186,7 @@ internal class TokenDetailsStateFactory( name = currency.name, symbol = currency.symbol, network = currency.network.name, - addresses = addresses.map { - AddressModel( - value = it.value, - type = AddressModel.Type.valueOf(it.type.name), - ) - }, + addresses = networkAddress.availableAddresses.mapToAddressModels(currency).toImmutableList(), onCopyClick = sendCopyAnalyticsEvent, onShareClick = sendShareAnalyticsEvent, ), @@ -199,20 +194,16 @@ internal class TokenDetailsStateFactory( ) } - fun getStateWithChooseAddressBottomSheet(addresses: List
): TokenDetailsState { + fun getStateWithChooseAddressBottomSheet( + currency: CryptoCurrency, + networkAddress: NetworkAddress, + ): TokenDetailsState { return currentStateProvider().copy( bottomSheetConfig = TangemBottomSheetConfig( isShow = true, onDismissRequest = clickIntents::onDismissBottomSheet, content = ChooseAddressBottomSheetConfig( - addressModels = addresses - .map { address -> - AddressModel( - value = address.value, - type = AddressModel.Type.valueOf(address.type.name), - ) - } - .toImmutableList(), + addressModels = networkAddress.availableAddresses.mapToAddressModels(currency).toImmutableList(), onClick = clickIntents::onAddressTypeSelected, ), ), diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt index b1496b2e0c..7be83bff9e 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/viewmodels/TokenDetailsViewModel.kt @@ -23,12 +23,12 @@ import com.tangem.domain.tokens.* import com.tangem.domain.tokens.legacy.TradeCryptoAction import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.domain.tokens.model.NetworkAddress import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent import com.tangem.domain.tokens.models.analytics.TokenScreenAnalyticsEvent import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase -import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase import com.tangem.domain.wallets.usecase.GetUserWalletUseCase @@ -67,7 +67,6 @@ internal class TokenDetailsViewModel @Inject constructor( private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, - private val walletManagersFacade: WalletManagersFacade, private val isDemoCardUseCase: IsDemoCardUseCase, private val reduxStateHolder: ReduxStateHolder, private val analyticsEventsHandler: AnalyticsEventHandler, @@ -303,19 +302,15 @@ internal class TokenDetailsViewModel @Inject constructor( } override fun onReceiveClick() { - analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol)) + val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return viewModelScope.launch(dispatchers.io) { - val addresses = walletManagersFacade.getAddress( - userWalletId = userWalletId, - network = cryptoCurrency.network, - ) - - analyticsEventsHandler.send(event = TokenReceiveAnalyticsEvent.ReceiveScreenOpened) + analyticsEventsHandler.send(TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrency.symbol)) + analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ReceiveScreenOpened) uiState = stateFactory.getStateWithReceiveBottomSheet( currency = cryptoCurrency, - addresses = addresses, + networkAddress = networkAddress, sendCopyAnalyticsEvent = { analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(cryptoCurrency.symbol)) }, @@ -378,22 +373,23 @@ internal class TokenDetailsViewModel @Inject constructor( } private fun openExplorer() { - viewModelScope.launch(dispatchers.io) { - val addresses = walletManagersFacade.getAddress( - userWalletId = userWalletId, - network = cryptoCurrency.network, - ) + val currencyStatus = cryptoCurrencyStatus ?: return - if (addresses.size == 1) { - router.openUrl( - url = getExploreUrlUseCase( - userWalletId = userWalletId, - currency = cryptoCurrency, - addressType = AddressType.Default, - ), - ) - } else { - uiState = stateFactory.getStateWithChooseAddressBottomSheet(addresses = addresses) + viewModelScope.launch(dispatchers.io) { + when (val addresses = currencyStatus.value.networkAddress) { + is NetworkAddress.Selectable -> { + uiState = stateFactory.getStateWithChooseAddressBottomSheet(cryptoCurrency, addresses) + } + is NetworkAddress.Single -> { + router.openUrl( + url = getExploreUrlUseCase( + userWalletId = userWalletId, + currency = cryptoCurrency, + addressType = AddressType.Default, + ), + ) + } + null -> Unit } } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt index bc1c275b2f..f38f77ee57 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt @@ -19,6 +19,7 @@ import com.tangem.core.navigation.AppScreen import com.tangem.core.ui.components.bottomsheets.chooseaddress.ChooseAddressBottomSheetConfig import com.tangem.core.ui.components.bottomsheets.tokenreceive.AddressModel import com.tangem.core.ui.components.bottomsheets.tokenreceive.TokenReceiveBottomSheetConfig +import com.tangem.core.ui.components.bottomsheets.tokenreceive.mapToAddressModels import com.tangem.core.ui.components.transactions.state.TxHistoryState import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.WrappedList @@ -42,10 +43,7 @@ import com.tangem.domain.settings.* import com.tangem.domain.tokens.* import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.legacy.TradeCryptoAction -import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.model.CryptoCurrencyStatus -import com.tangem.domain.tokens.model.NetworkGroup -import com.tangem.domain.tokens.model.TokenList +import com.tangem.domain.tokens.model.* import com.tangem.domain.tokens.models.analytics.TokenReceiveAnalyticsEvent import com.tangem.domain.tokens.models.analytics.TokenScreenAnalyticsEvent import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase @@ -688,20 +686,11 @@ internal class WalletViewModel @Inject constructor( } override fun onReceiveClick(cryptoCurrencyStatus: CryptoCurrencyStatus) { - val state = uiState as? WalletState.ContentState ?: return - analyticsEventsHandler.send( event = TokenScreenAnalyticsEvent.ButtonReceive(cryptoCurrencyStatus.currency.symbol), ) viewModelScope.launch(dispatchers.io) { - val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex) - - val addresses = walletManagersFacade.getAddress( - userWalletId = userWallet.walletId, - network = cryptoCurrencyStatus.currency.network, - ) - analyticsEventsHandler.send(event = TokenReceiveAnalyticsEvent.ReceiveScreenOpened) val currency = cryptoCurrencyStatus.currency @@ -710,12 +699,11 @@ internal class WalletViewModel @Inject constructor( name = currency.name, symbol = currency.symbol, network = currency.network.name, - addresses = addresses.map { - AddressModel( - value = it.value, - type = AddressModel.Type.valueOf(it.type.name), - ) - }, + addresses = cryptoCurrencyStatus.value.networkAddress + ?.availableAddresses + ?.mapToAddressModels(currency) + .orEmpty() + .toImmutableList(), onCopyClick = { analyticsEventsHandler.send(TokenReceiveAnalyticsEvent.ButtonCopyAddress(currency.symbol)) }, @@ -820,41 +808,39 @@ internal class WalletViewModel @Inject constructor( private fun openExplorer() { val state = uiState as? WalletState.ContentState ?: return - val currency = singleWalletCryptoCurrencyStatus?.currency ?: return + val currencyStatus = singleWalletCryptoCurrencyStatus ?: return + val currency = currencyStatus.currency viewModelScope.launch(dispatchers.main) { val userWalletId = getWallet(state.walletsListConfig.selectedWalletIndex).walletId - val addresses = walletManagersFacade.getAddress(userWalletId = userWalletId, network = currency.network) - - if (addresses.size == 1) { - router.openUrl( - url = getExploreUrlUseCase( - userWalletId = userWalletId, - currency = currency, - addressType = AddressType.Default, - ), - ) - } else { - uiState = stateFactory.getStateWithOpenWalletBottomSheet( - ChooseAddressBottomSheetConfig( - addressModels = addresses - .map { address -> - AddressModel( - value = address.value, - type = AddressModel.Type.valueOf(address.type.name), + when (val addresses = currencyStatus.value.networkAddress) { + is NetworkAddress.Selectable -> { + uiState = stateFactory.getStateWithOpenWalletBottomSheet( + ChooseAddressBottomSheetConfig( + addressModels = addresses.availableAddresses + .mapToAddressModels(currency) + .toImmutableList(), + onClick = { + onAddressTypeSelected( + userWalletId = userWalletId, + currency = currency, + addressModel = it, ) - } - .toImmutableList(), - onClick = { - onAddressTypeSelected( - userWalletId = userWalletId, - currency = currency, - addressModel = it, - ) - }, - ), - ) + }, + ), + ) + } + is NetworkAddress.Single -> { + router.openUrl( + url = getExploreUrlUseCase( + userWalletId = userWalletId, + currency = currency, + addressType = AddressType.Default, + ), + ) + } + null -> Unit } } } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 85f5969ccc..22229e35a8 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ spr-client = "3.6.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.3-404" +tangemBlockchainSdk = "release-app_5.3-405" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.3-313" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds