Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-29 19:27:56 +05:00
commit fbec0d5a58
8 changed files with 101 additions and 7 deletions

View file

@ -22,6 +22,15 @@ interface CardCryptoCurrencyFactory {
@Throws
suspend fun create(userWalletId: UserWalletId, network: Network): List<CryptoCurrency>
/**
* Universal method for creating list of [CryptoCurrency] in [network] for any card
*
* @param userWalletId user wallet id that determines type of card
* @param network network
*/
@Throws
suspend fun createByRawId(userWalletId: UserWalletId, network: Network.RawID): List<CryptoCurrency>
/**
* Create currencies for multi currency card
*

View file

@ -3,6 +3,8 @@ package com.tangem.data.common.currency
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.toBlockchain
import com.tangem.blockchainsdk.utils.toNetworkId
import com.tangem.datasource.local.token.UserTokensResponseStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.common.TapWorkarounds.isTestCard
@ -54,6 +56,32 @@ internal class DefaultCardCryptoCurrencyFactory(
return createPrimaryCurrencyForSingleCurrencyCard(userWallet.scanResponse).let(::listOf)
}
override suspend fun createByRawId(userWalletId: UserWalletId, networkRawId: Network.RawID): List<CryptoCurrency> {
val userWallet = userWalletsStore.getSyncStrict(key = userWalletId)
val blockchain = networkRawId.toBlockchain()
// multi-currency wallet
if (userWallet.isMultiCurrency) {
return getMultiWalletCurrenciesByRawId(
userWallet = userWallet,
rawIds = setOf(networkRawId),
)[networkRawId].orEmpty()
}
// check if the blockchain of single-currency wallet is the same as network
val cardBlockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
if (cardBlockchain != blockchain) return emptyList()
// single-currency wallet with token (NODL)
if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
return createCurrenciesForSingleCurrencyCardWithToken(userWallet.scanResponse)
}
// single-currency wallet
return createPrimaryCurrencyForSingleCurrencyCard(userWallet.scanResponse).let(::listOf)
}
override suspend fun createCurrenciesForMultiCurrencyCard(
userWallet: UserWallet,
networks: Set<Network>,
@ -123,6 +151,24 @@ internal class DefaultCardCryptoCurrencyFactory(
.groupBy(CryptoCurrency::network)
}
private suspend fun getMultiWalletCurrenciesByRawId(
userWallet: UserWallet,
rawIds: Set<Network.RawID>,
): Map<Network.RawID, List<CryptoCurrency>> {
val response = userTokensResponseStore.getSyncOrNull(userWalletId = userWallet.walletId)
?: return emptyMap()
val responseCurrenciesFactory = ResponseCryptoCurrenciesFactory(excludedBlockchains)
val networkIds = rawIds.map { it.toBlockchain().toNetworkId() }
return responseCurrenciesFactory.createCurrencies(
tokens = response.tokens.filter { token -> token.networkId in networkIds },
scanResponse = userWallet.scanResponse,
)
.groupBy { it.network.id.rawId }
}
private fun getSingleWalletCurrencies(scanResponse: ScanResponse): SingleWalletCurrencies {
val resolver = scanResponse.cardTypesResolver
val blockchain = resolver.getBlockchain()

View file

@ -62,6 +62,23 @@ internal class DefaultNetworksRepository(
}
}
override suspend fun getNetworkAddresses(
userWalletId: UserWalletId,
network: Network.RawID,
): List<CryptoCurrencyAddress> {
return runCatching { cardCryptoCurrencyFactory.createByRawId(userWalletId = userWalletId, network = network) }
.getOrElse {
Timber.e(it, "Unable to create wallet currencies")
return emptyList()
}
.map { currency ->
CryptoCurrencyAddress(
cryptoCurrency = currency,
address = getDefaultAddress(userWalletId, currency.network),
)
}
}
private suspend fun fetchPendingTransactions(
userWalletId: UserWalletId,
network: Network,

View file

@ -21,4 +21,6 @@ interface NetworksRepository {
* @param network network
*/
suspend fun getNetworkAddresses(userWalletId: UserWalletId, network: Network): List<CryptoCurrencyAddress>
suspend fun getNetworkAddresses(userWalletId: UserWalletId, network: Network.RawID): List<CryptoCurrencyAddress>
}

View file

@ -9,6 +9,10 @@ class GetNetworkAddressesUseCase(
private val networksRepository: NetworksRepository,
) {
suspend fun invokeSync(userWalletId: UserWalletId, networkRawId: Network.RawID): List<CryptoCurrencyAddress> {
return networksRepository.getNetworkAddresses(userWalletId, networkRawId)
}
suspend fun invokeSync(userWalletId: UserWalletId, network: Network): List<CryptoCurrencyAddress> {
return networksRepository.getNetworkAddresses(userWalletId, network)
}

View file

@ -142,8 +142,10 @@ internal class SendDestinationModel @Inject constructor(
private fun initSenderAddress() {
modelScope.launch {
senderAddresses.value = getNetworkAddressesUseCase.invokeSync(userWalletId, cryptoCurrency.network)
.filter { cryptoCurrency.id == it.cryptoCurrency.id }
senderAddresses.value = getNetworkAddressesUseCase.invokeSync(
userWalletId = userWalletId,
networkRawId = cryptoCurrency.network.id.rawId,
).filter { cryptoCurrency.id == it.cryptoCurrency.id }
}
senderAddresses.onEach {
getWalletsAndRecent()
@ -212,13 +214,19 @@ internal class SendDestinationModel @Inject constructor(
val addresses = if (!wallet.isMultiCurrency) {
getCryptoCurrencyUseCase(wallet.walletId).getOrNull()?.let {
if (it.network.id == cryptoCurrencyNetwork.id) {
getNetworkAddressesUseCase.invokeSync(wallet.walletId, it.network)
getNetworkAddressesUseCase.invokeSync(
userWalletId = wallet.walletId,
networkRawId = it.network.id.rawId,
)
} else {
null
}
}
} else {
getNetworkAddressesUseCase.invokeSync(wallet.walletId, cryptoCurrencyNetwork)
getNetworkAddressesUseCase.invokeSync(
userWalletId = wallet.walletId,
networkRawId = cryptoCurrencyNetwork.id.rawId,
)
}
wallet to addresses
}

View file

@ -430,13 +430,19 @@ internal class SendModel @Inject constructor(
cryptoCurrencyId = cryptoCurrency.id.value,
).getOrNull()?.let {
if (it.network.id == cryptoCurrency.network.id) {
getNetworkAddressesUseCase.invokeSync(wallet.walletId, it.network)
getNetworkAddressesUseCase.invokeSync(
userWalletId = wallet.walletId,
networkRawId = it.network.id.rawId,
)
} else {
null
}
}
} else {
getNetworkAddressesUseCase.invokeSync(wallet.walletId, cryptoCurrency.network)
getNetworkAddressesUseCase.invokeSync(
userWalletId = wallet.walletId,
networkRawId = cryptoCurrency.network.id.rawId,
)
}
addresses?.map { (cryptoCurrency, address) ->
AvailableWallet(

View file

@ -7,4 +7,6 @@ import com.tangem.domain.models.network.Network
fun Network.toBlockchain(): Blockchain = id.toBlockchain()
/** Converts [Network.ID] to [Blockchain] */
fun Network.ID.toBlockchain(): Blockchain = Blockchain.fromId(id = rawId.value)
fun Network.ID.toBlockchain(): Blockchain = rawId.toBlockchain()
fun Network.RawID.toBlockchain(): Blockchain = Blockchain.fromId(id = value)