Updated on 2026-08-14
This commit is contained in:
parent
e33bd4d849
commit
b98b0f659c
138 changed files with 686 additions and 346 deletions
|
|
@ -15,6 +15,8 @@ import com.tangem.domain.models.network.Network
|
|||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
/**
|
||||
* Default implementation of factory for creating list of [CryptoCurrency] for selected card
|
||||
|
|
@ -39,7 +41,7 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
val blockchain = Blockchain.fromNetworkId(networkId = network.backendId)
|
||||
|
||||
// multi-currency wallet
|
||||
if (userWallet.isMultiCurrency) {
|
||||
if (userWallet !is UserWallet.Cold || userWallet.isMultiCurrency) {
|
||||
return getMultiWalletCurrencies(userWallet = userWallet, networks = setOf(network))[network].orEmpty()
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +64,7 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
val blockchain = networkRawId.toBlockchain()
|
||||
|
||||
// multi-currency wallet
|
||||
if (userWallet.isMultiCurrency) {
|
||||
if (userWallet.isMultiCurrency || userWallet !is UserWallet.Cold) {
|
||||
return getMultiWalletCurrenciesByRawId(
|
||||
userWallet = userWallet,
|
||||
rawIds = setOf(networkRawId),
|
||||
|
|
@ -146,7 +148,7 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
tokens = response.tokens.filter { token ->
|
||||
networks.any { it.backendId == token.networkId && it.derivationPath.value == token.derivationPath }
|
||||
},
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
.groupBy(CryptoCurrency::network)
|
||||
}
|
||||
|
|
@ -164,7 +166,7 @@ internal class DefaultCardCryptoCurrencyFactory(
|
|||
|
||||
return responseCurrenciesFactory.createCurrencies(
|
||||
tokens = response.tokens.filter { token -> token.networkId in networkIds },
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
.groupBy { it.network.id.rawId }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
)
|
||||
}
|
||||
|
||||
data class CreateDefaultForMultiWalletModel(val multiWallet: UserWallet, val expected: List<CryptoCurrency>)
|
||||
data class CreateDefaultForMultiWalletModel(val multiWallet: UserWallet.Cold, val expected: List<CryptoCurrency>)
|
||||
|
||||
@Nested
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
|
|
@ -381,7 +381,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
}
|
||||
|
||||
data class CreatePrimaryCurrencyForSingleWalletModel(
|
||||
val singleWallet: UserWallet,
|
||||
val singleWallet: UserWallet.Cold,
|
||||
val expected: Result<CryptoCurrency>,
|
||||
)
|
||||
|
||||
|
|
@ -424,7 +424,7 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
|
||||
private fun provideTestModels() = listOf(
|
||||
CreateForSingleWalletWithTokenModel(
|
||||
singleWalletWithToken = UserWallet(
|
||||
singleWalletWithToken = UserWallet.Cold(
|
||||
name = "NODL",
|
||||
walletId = UserWalletId("011"),
|
||||
cardsInWallet = setOf(),
|
||||
|
|
@ -457,13 +457,13 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
}
|
||||
|
||||
data class CreateForSingleWalletWithTokenModel(
|
||||
val singleWalletWithToken: UserWallet,
|
||||
val singleWalletWithToken: UserWallet.Cold,
|
||||
val isPrimaryTokenExpected: Boolean = false,
|
||||
val expected: Result<List<CryptoCurrency>>,
|
||||
)
|
||||
|
||||
private fun createMultiWallet(cardId: String? = null, batchId: String? = null): UserWallet {
|
||||
return UserWallet(
|
||||
private fun createMultiWallet(cardId: String? = null, batchId: String? = null): UserWallet.Cold {
|
||||
return UserWallet.Cold(
|
||||
name = "Wallet 1",
|
||||
walletId = UserWalletId("011"),
|
||||
cardsInWallet = setOf(),
|
||||
|
|
@ -483,8 +483,8 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createSingleWallet(batchId: String? = null, addWalletData: Boolean = false): UserWallet {
|
||||
return UserWallet(
|
||||
private fun createSingleWallet(batchId: String? = null, addWalletData: Boolean = false): UserWallet.Cold {
|
||||
return UserWallet.Cold(
|
||||
name = "Note",
|
||||
walletId = UserWalletId("011"),
|
||||
cardsInWallet = setOf(),
|
||||
|
|
@ -515,8 +515,8 @@ internal class DefaultCardCryptoCurrencyFactoryTest {
|
|||
)
|
||||
}
|
||||
|
||||
private fun createSingleWalletWithToken(): UserWallet {
|
||||
return UserWallet(
|
||||
private fun createSingleWalletWithToken(): UserWallet.Cold {
|
||||
return UserWallet.Cold(
|
||||
name = "NODL",
|
||||
walletId = UserWalletId("011"),
|
||||
cardsInWallet = setOf(),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while finding token"
|
||||
|
|
@ -152,7 +153,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while creating coin"
|
||||
|
|
@ -189,7 +190,7 @@ internal class DefaultCustomTokensRepository(
|
|||
networkFactory.create(
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
),
|
||||
) {
|
||||
"Network [$networkId] not found while creating custom token"
|
||||
|
|
@ -249,7 +250,7 @@ internal class DefaultCustomTokensRepository(
|
|||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
||||
"User wallet [$userWalletId] not found while getting supported networks"
|
||||
}
|
||||
val scanResponse = userWallet.scanResponse
|
||||
val scanResponse = userWallet.requireColdWallet().scanResponse // TODO [REDACTED_TASK_KEY]
|
||||
|
||||
Blockchain.entries
|
||||
.mapNotNull { blockchain ->
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
|||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.pagination.BatchFetchResult
|
||||
import com.tangem.pagination.BatchListSource
|
||||
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
|
||||
|
|
@ -80,7 +81,7 @@ internal class DefaultManageTokensRepository(
|
|||
subFetcher = { request, _, isFirstBatchFetching ->
|
||||
val userWallet = request.params.userWalletId?.let(userWalletsStore::getSyncStrict)
|
||||
|
||||
if (userWallet?.scanResponse?.card?.isTestCard == true) {
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isTestCard) {
|
||||
fetchTestnetCurrencies(userWallet, request)
|
||||
} else {
|
||||
fetchCurrencies(
|
||||
|
|
@ -143,13 +144,13 @@ internal class DefaultManageTokensRepository(
|
|||
managedCryptoCurrencyFactory.createWithCustomTokens(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
} else {
|
||||
managedCryptoCurrencyFactory.create(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
scanResponse = userWallet?.scanResponse,
|
||||
scanResponse = userWallet?.requireColdWallet()?.scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -179,7 +180,7 @@ internal class DefaultManageTokensRepository(
|
|||
testnetTokensConfig
|
||||
},
|
||||
tokensResponse = getSavedUserTokensResponseSync(userWallet.walletId),
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
|
|
@ -191,14 +192,16 @@ internal class DefaultManageTokensRepository(
|
|||
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet) =
|
||||
userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(userWallet.scanResponse),
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
||||
private fun getSupportedBlockchains(userWallet: UserWallet?): List<Blockchain> {
|
||||
return userWallet?.scanResponse?.let {
|
||||
it.card.supportedBlockchains(it.cardTypesResolver, excludedBlockchains)
|
||||
return (userWallet as? UserWallet.Cold)?.scanResponse?.let {
|
||||
it.card.supportedBlockchains(it.cardTypesResolver, excludedBlockchains) // TODO [REDACTED_TASK_KEY]
|
||||
} ?: Blockchain.entries.filter {
|
||||
!it.isTestnet() && it !in excludedBlockchains
|
||||
}
|
||||
|
|
@ -285,6 +288,10 @@ internal class DefaultManageTokensRepository(
|
|||
userWallet: UserWallet,
|
||||
blockchain: Blockchain,
|
||||
): CurrencyUnsupportedState? {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return null
|
||||
}
|
||||
|
||||
val canHandleBlockchain = userWallet.scanResponse.card.canHandleBlockchain(
|
||||
blockchain = blockchain,
|
||||
cardTypesResolver = userWallet.cardTypesResolver,
|
||||
|
|
@ -302,6 +309,10 @@ internal class DefaultManageTokensRepository(
|
|||
userWallet: UserWallet,
|
||||
blockchain: Blockchain,
|
||||
): CurrencyUnsupportedState.Token? {
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return null
|
||||
}
|
||||
|
||||
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
|
||||
val supportedTokens = userWallet.scanResponse.card.supportedTokens(
|
||||
cardTypesResolver,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.markets.*
|
|||
import com.tangem.domain.markets.repositories.MarketsTokenRepository
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.pagination.*
|
||||
import com.tangem.pagination.fetcher.LimitOffsetBatchFetcher
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
|
|
@ -250,13 +251,13 @@ internal class DefaultMarketsTokenRepository(
|
|||
cryptoCurrencyFactory.createCoin(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
} else {
|
||||
val currencyNetwork = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
) ?: return null
|
||||
|
||||
cryptoCurrencyFactory.createToken(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.datasource.local.userwallet.UserWalletsStore
|
|||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.core.utils.eitherOn
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusFetcher
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
|
|
@ -52,7 +53,7 @@ internal class DefaultMultiNetworkStatusFetcher @Inject constructor(
|
|||
},
|
||||
)
|
||||
|
||||
val cardTypesResolver = userWallet.cardTypesResolver
|
||||
val cardTypesResolver = userWallet.requireColdWallet().cardTypesResolver // TODO [REDACTED_TASK_KEY]
|
||||
val isWalletSupported = with(cardTypesResolver) {
|
||||
isMultiwalletAllowed() || isSingleWalletWithToken()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import com.tangem.data.networks.store.NetworksStatusesStore
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.models.network.NetworkStatus
|
||||
import com.tangem.domain.networks.multi.MultiNetworkStatusProducer
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -47,7 +48,7 @@ internal class DefaultMultiNetworkStatusProducer @AssistedInject constructor(
|
|||
val network = networkFactory.create(
|
||||
networkId = status.id,
|
||||
derivationPath = status.id.derivationPath,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
) ?: return@mapNotNullTo null
|
||||
|
||||
NetworkStatus(network = network, value = status.value)
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ internal class DefaultMultiNetworkStatusFetcherTest {
|
|||
coEvery { networksStatusesStore.setSourceAsCache(params.userWalletId, params.networks) } returns Unit
|
||||
every { userWalletsStore.getSyncStrict(key = userWalletId) } returns userWallet
|
||||
|
||||
mockkStatic(UserWallet::cardTypesResolver)
|
||||
mockkStatic(UserWallet.Cold::cardTypesResolver)
|
||||
every { userWallet.cardTypesResolver } returns cardTypesResolver
|
||||
coEvery { cardTypesResolver.isMultiwalletAllowed() } returns true
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ internal class DefaultMultiNetworkStatusFetcherTest {
|
|||
coEvery { networksStatusesStore.setSourceAsCache(params.userWalletId, params.networks) } returns Unit
|
||||
every { userWalletsStore.getSyncStrict(key = userWalletId) } returns userWallet
|
||||
|
||||
mockkStatic(UserWallet::cardTypesResolver)
|
||||
mockkStatic(UserWallet.Cold::cardTypesResolver)
|
||||
every { userWallet.cardTypesResolver } returns cardTypesResolver
|
||||
coEvery { cardTypesResolver.isMultiwalletAllowed() } returns false
|
||||
coEvery { cardTypesResolver.isSingleWalletWithToken() } returns true
|
||||
|
|
@ -193,7 +193,7 @@ internal class DefaultMultiNetworkStatusFetcherTest {
|
|||
coEvery { networksStatusesStore.setSourceAsCache(params.userWalletId, params.networks) } returns Unit
|
||||
every { userWalletsStore.getSyncStrict(key = userWalletId) } returns userWallet
|
||||
|
||||
mockkStatic(UserWallet::cardTypesResolver)
|
||||
mockkStatic(UserWallet.Cold::cardTypesResolver)
|
||||
every { userWallet.cardTypesResolver } returns cardTypesResolver
|
||||
coEvery { cardTypesResolver.isMultiwalletAllowed() } returns true
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ internal class DefaultMultiNetworkStatusFetcherTest {
|
|||
coEvery { networksStatusesStore.setSourceAsCache(params.userWalletId, params.networks) } returns Unit
|
||||
every { userWalletsStore.getSyncStrict(key = userWalletId) } returns userWallet
|
||||
|
||||
mockkStatic(UserWallet::cardTypesResolver)
|
||||
mockkStatic(UserWallet.Cold::cardTypesResolver)
|
||||
every { userWallet.cardTypesResolver } returns cardTypesResolver
|
||||
coEvery { cardTypesResolver.isMultiwalletAllowed() } returns true
|
||||
|
||||
|
|
@ -367,7 +367,7 @@ internal class DefaultMultiNetworkStatusFetcherTest {
|
|||
coEvery { networksStatusesStore.setSourceAsCache(params.userWalletId, params.networks) } returns Unit
|
||||
every { userWalletsStore.getSyncStrict(key = userWalletId) } returns userWallet
|
||||
|
||||
mockkStatic(UserWallet::cardTypesResolver)
|
||||
mockkStatic(UserWallet.Cold::cardTypesResolver)
|
||||
every { userWallet.cardTypesResolver } returns cardTypesResolver
|
||||
coEvery { cardTypesResolver.isMultiwalletAllowed() } returns false
|
||||
coEvery { cardTypesResolver.isSingleWalletWithToken() } returns false
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.nft.models.NFTSalePrice
|
|||
import com.tangem.domain.nft.repository.NFTRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.features.nft.NFTFeatureToggles
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
|
|
@ -204,7 +205,7 @@ internal class DefaultNFTRepository @Inject constructor(
|
|||
networkFactory.create(
|
||||
blockchain = it,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.onramp.model.HotCryptoCurrency
|
|||
import com.tangem.domain.onramp.repositories.HotCryptoRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.runCatching
|
||||
|
|
@ -90,7 +91,7 @@ internal class DefaultHotCryptoRepository(
|
|||
?: error("UserWalletId [$userWalletId] not found")
|
||||
|
||||
HotCryptoCurrencyConverter(
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
imageHost = it.imageHost,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
)
|
||||
|
|
@ -170,6 +171,10 @@ internal class DefaultHotCryptoRepository(
|
|||
|
||||
// TODO: [REDACTED_JIRA]
|
||||
private fun UserWallet.canHandleHotCrypto(hotToken: HotCryptoResponse.Token): Boolean {
|
||||
if (this !is UserWallet.Cold) {
|
||||
return true // TODO [REDACTED_TASK_KEY]
|
||||
}
|
||||
|
||||
val isToken = hotToken.contractAddress != null && hotToken.decimalCount != null
|
||||
val blockchain = hotToken.networkId?.let { Blockchain.fromNetworkId(it) } ?: return false
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
|
|||
import com.tangem.domain.staking.repositories.StakingRepository
|
||||
import com.tangem.domain.staking.toggles.StakingFeatureToggles
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isCardano
|
||||
|
|
@ -257,6 +258,11 @@ internal class DefaultStakingRepository(
|
|||
val userWallet = getUserWalletUseCase(userWalletId).getOrElse {
|
||||
error("Failed to get user wallet")
|
||||
}
|
||||
|
||||
if (userWallet !is UserWallet.Cold) {
|
||||
return false
|
||||
}
|
||||
|
||||
val blockchainId = cryptoCurrency.network.rawId
|
||||
return when {
|
||||
isSolana(blockchainId) -> INVALID_BATCHES_FOR_SOLANA.contains(userWallet.scanResponse.card.batchId)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import com.tangem.domain.staking.fetcher.YieldBalanceFetcherParams
|
|||
import com.tangem.domain.staking.model.StakingID
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
|||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isLocked
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
|
@ -222,7 +225,9 @@ internal class DefaultCurrenciesRepository(
|
|||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(userWallet.scanResponse)
|
||||
val currency = cardCryptoCurrencyFactory.createPrimaryCurrencyForSingleCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse,
|
||||
)
|
||||
fetchExpressAssetsByNetworkIds(userWalletId, listOf(currency), refresh)
|
||||
currency
|
||||
}
|
||||
|
|
@ -233,7 +238,7 @@ internal class DefaultCurrenciesRepository(
|
|||
refresh: Boolean,
|
||||
): List<CryptoCurrency> {
|
||||
return withContext(dispatchers.io) {
|
||||
val scanResponse = getUserWallet(userWalletId).scanResponse
|
||||
val scanResponse = getUserWallet(userWalletId).requireColdWallet().scanResponse
|
||||
|
||||
val currencies = if (scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
|
||||
cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(scanResponse = scanResponse)
|
||||
|
|
@ -257,7 +262,7 @@ internal class DefaultCurrenciesRepository(
|
|||
ensureIsCorrectUserWallet(userWallet, isMultiCurrencyWalletExpected = false)
|
||||
|
||||
val currency = cardCryptoCurrencyFactory.createCurrenciesForSingleCurrencyCardWithToken(
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
)
|
||||
.find { it.id == id }
|
||||
requireNotNull(currency) { "Unable to find currency with provided ID: $id" }
|
||||
|
|
@ -297,7 +302,7 @@ internal class DefaultCurrenciesRepository(
|
|||
},
|
||||
)
|
||||
|
||||
responseCurrenciesFactory.createCurrencies(storedTokens, userWallet.scanResponse)
|
||||
responseCurrenciesFactory.createCurrencies(storedTokens, userWallet.requireColdWallet().scanResponse)
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCachedCurrenciesSync(userWalletId: UserWalletId) =
|
||||
|
|
@ -312,7 +317,7 @@ internal class DefaultCurrenciesRepository(
|
|||
},
|
||||
)
|
||||
|
||||
responseCurrenciesFactory.createCurrencies(storedTokens, userWallet.scanResponse)
|
||||
responseCurrenciesFactory.createCurrencies(storedTokens, userWallet.requireColdWallet().scanResponse)
|
||||
}
|
||||
|
||||
override suspend fun getMultiCurrencyWalletCurrency(
|
||||
|
|
@ -337,7 +342,7 @@ internal class DefaultCurrenciesRepository(
|
|||
responseCurrenciesFactory.createCurrency(
|
||||
currencyId = id,
|
||||
response = response,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +374,7 @@ internal class DefaultCurrenciesRepository(
|
|||
it.derivationPath == derivationPath.value
|
||||
} ?: error("Coin in this network $networkId not found")
|
||||
|
||||
val coin = responseCurrenciesFactory.createCurrency(storedCoin, userWallet.scanResponse)
|
||||
val coin = responseCurrenciesFactory.createCurrency(storedCoin, userWallet.requireColdWallet().scanResponse)
|
||||
|
||||
coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
|
||||
}
|
||||
|
|
@ -488,7 +493,7 @@ internal class DefaultCurrenciesRepository(
|
|||
token = token,
|
||||
networkId = networkId,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
) ?: error("Unable to create token")
|
||||
}
|
||||
|
||||
|
|
@ -510,7 +515,7 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
responseCurrenciesFactory.createCurrencies(
|
||||
response = storedTokens.copy(tokens = filterResponse),
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
|
@ -544,8 +549,8 @@ internal class DefaultCurrenciesRepository(
|
|||
lazyMessage = { "Saved tokens empty. Can not perform add currencies action" },
|
||||
)
|
||||
userTokensSaver.push(
|
||||
userWalletId,
|
||||
savedCurrencies,
|
||||
userWalletId = userWalletId,
|
||||
response = savedCurrencies,
|
||||
onFailSend = {
|
||||
throw IllegalStateException("Unable to push tokens")
|
||||
},
|
||||
|
|
@ -556,7 +561,7 @@ internal class DefaultCurrenciesRepository(
|
|||
return getSavedUserTokensResponse(userWallet.walletId).map { storedTokens ->
|
||||
responseCurrenciesFactory.createCurrencies(
|
||||
response = storedTokens,
|
||||
scanResponse = userWallet.scanResponse,
|
||||
scanResponse = userWallet.requireColdWallet().scanResponse,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -579,7 +584,7 @@ internal class DefaultCurrenciesRepository(
|
|||
private suspend fun fetchTokens(userWallet: UserWallet) {
|
||||
val userWalletId = userWallet.walletId
|
||||
|
||||
val response = if (checkIsEmptyDemoWallet(userWallet)) {
|
||||
val response = if (userWallet is UserWallet.Cold && checkIsEmptyDemoWallet(userWallet)) {
|
||||
createDefaultUserTokensResponse(userWallet)
|
||||
} else {
|
||||
safeApiCall({ tangemTechApi.getUserTokens(userWalletId.stringValue).bind() }) {
|
||||
|
|
@ -596,7 +601,7 @@ internal class DefaultCurrenciesRepository(
|
|||
fetchExpressAssetsByNetworkIds(userWalletId, compatibleUserTokensResponse)
|
||||
}
|
||||
|
||||
private suspend fun checkIsEmptyDemoWallet(userWallet: UserWallet): Boolean {
|
||||
private suspend fun checkIsEmptyDemoWallet(userWallet: UserWallet.Cold): Boolean {
|
||||
val response = getSavedUserTokensResponseSync(key = userWallet.walletId)
|
||||
|
||||
return demoConfig.isDemoCardId(userWallet.cardId) && response == null
|
||||
|
|
@ -659,7 +664,9 @@ internal class DefaultCurrenciesRepository(
|
|||
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet) =
|
||||
userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(userWallet.scanResponse),
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyCard(
|
||||
userWallet.requireColdWallet().scanResponse,
|
||||
),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.visa.model.VisaTxHistoryItem
|
|||
import com.tangem.domain.visa.repository.VisaRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -142,7 +143,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
|||
|
||||
txDetailsFactory.create(
|
||||
transaction = transaction,
|
||||
walletBlockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain(),
|
||||
walletBlockchain = userWallet.requireColdWallet().scanResponse.cardTypesResolver.getBlockchain(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -153,7 +154,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
|||
val customerInfo = visaApiRequestMaker.request(userWalletId) { authHeader, _ ->
|
||||
visaApi.getCustomerInfo(
|
||||
authHeader = authHeader,
|
||||
cardId = userWallet.scanResponse.card.cardId,
|
||||
cardId = userWallet.requireColdWallet().scanResponse.card.cardId,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -198,7 +199,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
|||
}
|
||||
|
||||
private fun makeWalletAddresses(userWallet: UserWallet): Set<Address> {
|
||||
val walletBlockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
|
||||
val walletBlockchain = userWallet.requireColdWallet().scanResponse.cardTypesResolver.getBlockchain()
|
||||
|
||||
return walletBlockchain.makeAddresses(getCardPubKey(userWallet).hexToBytes())
|
||||
}
|
||||
|
|
@ -206,7 +207,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
|||
private fun getCardPubKey(userWallet: UserWallet): String {
|
||||
if (VisaConstants.IS_DEMO_MODE_ENABLED) return getDemoPublicKey()
|
||||
|
||||
val cardWallet = userWallet.scanResponse.card.wallets.firstOrNull {
|
||||
val cardWallet = userWallet.requireColdWallet().scanResponse.card.wallets.firstOrNull {
|
||||
it.curve == EllipticCurve.Secp256k1
|
||||
}
|
||||
requireNotNull(cardWallet) { "Visa card wallet not found" }
|
||||
|
|
@ -218,7 +219,7 @@ internal class DefaultVisaRepository @Inject constructor(
|
|||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
||||
"No user wallet found: $userWalletId"
|
||||
}
|
||||
if (!userWallet.scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||
error("VISA wallet required: $userWalletId")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.tangem.domain.visa.model.VisaCardActivationStatus
|
|||
import com.tangem.domain.visa.model.getAuthHeader
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
|
@ -52,7 +53,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
|||
it.code == ApiResponseError.HttpException.Code.UNAUTHORIZED
|
||||
) {
|
||||
userWalletsStore.update(userWalletId) { userWallet ->
|
||||
userWallet.copy(
|
||||
userWallet.requireColdWallet().copy(
|
||||
scanResponse = userWallet.scanResponse.copy(
|
||||
visaCardActivationStatus = VisaCardActivationStatus.RefreshTokenExpired,
|
||||
),
|
||||
|
|
@ -63,7 +64,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
|||
}
|
||||
|
||||
userWalletsStore.update(userWalletId) { userWallet ->
|
||||
userWallet.copy(
|
||||
userWallet.requireColdWallet().copy(
|
||||
scanResponse = userWallet.scanResponse.copy(
|
||||
visaCardActivationStatus = VisaCardActivationStatus.Activated(
|
||||
visaAuthTokens = newTokens,
|
||||
|
|
@ -93,7 +94,8 @@ internal class VisaApiRequestMaker @Inject constructor(
|
|||
@Throws
|
||||
private fun getAuthTokens(userWalletId: UserWalletId): VisaAuthTokens {
|
||||
val userWallet = findVisaUserWallet(userWalletId)
|
||||
val status = userWallet.scanResponse.visaCardActivationStatus ?: error("Visa card activation status not found")
|
||||
val status = userWallet.requireColdWallet().scanResponse.visaCardActivationStatus
|
||||
?: error("Visa card activation status not found")
|
||||
|
||||
if (status is VisaCardActivationStatus.RefreshTokenExpired) {
|
||||
throw RefreshTokenExpiredException()
|
||||
|
|
@ -106,7 +108,7 @@ internal class VisaApiRequestMaker @Inject constructor(
|
|||
val userWallet = requireNotNull(userWalletsStore.getSyncOrNull(userWalletId)) {
|
||||
"No user wallet found: $userWalletId"
|
||||
}
|
||||
if (!userWallet.scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||
if (!userWallet.requireColdWallet().scanResponse.cardTypesResolver.isVisaWallet()) {
|
||||
error("VISA wallet required: $userWalletId")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.network.NetworkAddress
|
||||
import com.tangem.domain.visa.model.VisaCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
import com.tangem.lib.visa.model.VisaContractInfo
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.DateTimeZone
|
||||
|
|
@ -33,7 +34,7 @@ internal class VisaCurrencyFactory @Inject constructor(
|
|||
val currencyNetwork = networkFactory.create(
|
||||
blockchain = Blockchain.Polygon,
|
||||
extraDerivationPath = null,
|
||||
derivationStyleProvider = userWallet.scanResponse.derivationStyleProvider,
|
||||
derivationStyleProvider = userWallet.requireColdWallet().scanResponse.derivationStyleProvider,
|
||||
canHandleTokens = true,
|
||||
) ?: error("Unable to create network for Visa currency")
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.tangem.data.walletconnect
|
|||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.walletconnect.repository.WalletConnectRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.tangem.domain.tokens.repository.CurrenciesRepository
|
|||
import com.tangem.domain.walletconnect.model.WcPairError
|
||||
import com.tangem.domain.walletconnect.model.WcSessionProposal.ProposalNetwork
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
|
||||
internal class AssociateNetworksDelegate(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.data.walletconnect.model.CAIP2
|
|||
import com.tangem.data.walletconnect.model.NamespaceKey
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.requireColdWallet
|
||||
|
||||
internal interface WcNamespaceConverter {
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ internal interface WcNamespaceConverter {
|
|||
return NetworkFactory(excludedBlockchains).create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = null,
|
||||
scanResponse = wallet.scanResponse,
|
||||
scanResponse = wallet.requireColdWallet().scanResponse, // TODO [REDACTED_TASK_KEY]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -89,6 +89,11 @@ internal class DefaultWalletsRepository(
|
|||
private suspend fun fetchSeedPhraseNotificationStatus(userWalletId: UserWalletId) {
|
||||
val userWallet = userWalletsStore.getSyncOrNull(key = userWalletId)
|
||||
|
||||
if (userWallet != null && userWallet !is UserWallet.Cold) {
|
||||
updateNotificationVisibility(id = userWalletId, value = SeedPhraseNotificationsStatus.NOT_NEEDED)
|
||||
return
|
||||
}
|
||||
|
||||
val status = if (userWallet?.isImported == false) {
|
||||
Status.NOT_NEEDED
|
||||
} else {
|
||||
|
|
@ -291,7 +296,7 @@ internal class DefaultWalletsRepository(
|
|||
override suspend fun associateWallets(applicationId: String, wallets: List<UserWallet>) =
|
||||
withContext(dispatchers.io) {
|
||||
val publicKeys = authProvider.getCardsPublicKeys()
|
||||
val walletsBody = wallets.map { userWallet ->
|
||||
val walletsBody = wallets.filterIsInstance<UserWallet.Cold>().map { userWallet ->
|
||||
WalletIdBodyConverter.convert(
|
||||
userWallet = userWallet,
|
||||
publicKeys = publicKeys.filterKeys { userWallet.cardsInWallet.contains(it) },
|
||||
|
|
|
|||
|
|
@ -176,12 +176,12 @@ class DefaultWalletsRepositoryTest {
|
|||
val card2PublicKey = "card2_public_key"
|
||||
|
||||
val userWallets = listOf(
|
||||
mockk<UserWallet> {
|
||||
mockk<UserWallet.Cold> {
|
||||
every { cardsInWallet } returns setOf(card1PublicKey)
|
||||
every { walletId } returns UserWalletId(wallet1Id)
|
||||
every { name } returns "Wallet 1"
|
||||
},
|
||||
mockk<UserWallet> {
|
||||
mockk<UserWallet.Cold> {
|
||||
every { cardsInWallet } returns setOf(card2PublicKey)
|
||||
every { walletId } returns UserWalletId(wallet2Id)
|
||||
every { name } returns "Wallet 2"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class WalletIdBodyConverterTest {
|
|||
// GIVEN
|
||||
val walletId = UserWalletId("1234567890abcdef")
|
||||
val walletName = "Test Wallet"
|
||||
val userWallet = UserWallet(
|
||||
val userWallet = UserWallet.Cold(
|
||||
walletId = walletId,
|
||||
name = walletName,
|
||||
cardsInWallet = setOf("card1", "card2"),
|
||||
|
|
@ -55,7 +55,7 @@ class WalletIdBodyConverterTest {
|
|||
// GIVEN
|
||||
val walletId = UserWalletId("1234567890abcdef")
|
||||
val walletName = "Test Wallet"
|
||||
val userWallet = UserWallet(
|
||||
val userWallet = UserWallet.Cold(
|
||||
walletId = walletId,
|
||||
name = walletName,
|
||||
cardsInWallet = emptySet(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue