Updated on 2026-08-14
This commit is contained in:
parent
81ef606a43
commit
665d56c9e8
30 changed files with 135 additions and 452 deletions
|
|
@ -2,7 +2,6 @@ package com.tangem.tap.routing.utils
|
|||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.qrscanning.models.SourceType
|
||||
import com.tangem.feature.qrscanning.QrScanningComponent
|
||||
import com.tangem.feature.referral.api.ReferralComponent
|
||||
|
|
@ -143,11 +142,7 @@ internal class ChildFactory @Inject constructor(
|
|||
AppRoute.ManageTokens.Source.ACCOUNT -> ManageTokensSource.ACCOUNT
|
||||
}
|
||||
|
||||
val mode = when (val portfolio = route.portfolioId) {
|
||||
is PortfolioId.Account -> ManageTokensMode.Account(portfolio.accountId)
|
||||
is PortfolioId.Wallet -> ManageTokensMode.Wallet(portfolio.userWalletId)
|
||||
null -> ManageTokensMode.None
|
||||
}
|
||||
val mode = route.accountId?.let { ManageTokensMode.Account(it) } ?: ManageTokensMode.None
|
||||
|
||||
createComponentChild(
|
||||
context = context,
|
||||
|
|
|
|||
|
|
@ -7,13 +7,12 @@ import android.os.Bundle
|
|||
import com.tangem.common.routing.bundle.RouteBundleParams
|
||||
import com.tangem.common.routing.bundle.bundle
|
||||
import com.tangem.common.routing.entity.InitScreenLaunchMode
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.core.decompose.navigation.Route
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.feedback.models.WalletMetaInfo
|
||||
import com.tangem.domain.markets.TokenMarketParams
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.models.serialization.SerializedBigDecimal
|
||||
|
|
@ -21,6 +20,7 @@ import com.tangem.domain.models.wallet.UserWalletId
|
|||
import com.tangem.domain.nft.models.NFTAsset
|
||||
import com.tangem.domain.onramp.model.OnrampSource
|
||||
import com.tangem.domain.pay.TangemPayDetailsConfig
|
||||
import com.tangem.domain.staking.model.StakingIntegrationID
|
||||
import com.tangem.domain.tokens.model.details.NavigationAction
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -128,8 +128,8 @@ sealed class AppRoute(val path: String) : Route {
|
|||
@Serializable
|
||||
data class ManageTokens(
|
||||
val source: Source,
|
||||
val portfolioId: PortfolioId? = null,
|
||||
) : AppRoute(path = "${source.name.lowercase()}/manage_tokens/${portfolioId?.stringValue}") {
|
||||
val accountId: AccountId? = null,
|
||||
) : AppRoute(path = "${source.name.lowercase()}/manage_tokens/${accountId?.value}") {
|
||||
|
||||
/**
|
||||
* Source of launching the screen.
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@ import com.tangem.blockchainsdk.utils.fromNetworkId
|
|||
import com.tangem.blockchainsdk.utils.toBlockchain
|
||||
import com.tangem.blockchainsdk.utils.toNetworkId
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.data.common.api.safeApiCall
|
||||
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.UserTokensResponseFactory
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.common.utils.retryOnError
|
||||
import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
|
||||
|
|
@ -22,7 +18,6 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.api.tangemTech.models.orDefault
|
||||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.domain.card.common.extensions.*
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
|
|
@ -48,24 +43,19 @@ import com.tangem.utils.coroutines.runSuspendCatching
|
|||
internal class DefaultManageTokensRepository(
|
||||
private val tangemTechApi: TangemTechApi,
|
||||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val userTokenSaver: UserTokensSaver,
|
||||
private val manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
||||
private val userTokensResponseStore: UserTokensResponseStore,
|
||||
private val testnetTokensStorage: TestnetTokensStorage,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
private val walletAccountsFetcher: WalletAccountsFetcher,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
networkFactory: NetworkFactory,
|
||||
) : ManageTokensRepository {
|
||||
|
||||
private val managedCryptoCurrencyFactory = ManagedCryptoCurrencyFactory(
|
||||
networkFactory = networkFactory,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
accountsFeatureToggles = accountsFeatureToggles,
|
||||
)
|
||||
private val userTokensResponseFactory = UserTokensResponseFactory()
|
||||
|
||||
// region getTokenListBatchFlow
|
||||
override fun getTokenListBatchFlow(
|
||||
|
|
@ -92,10 +82,7 @@ internal class DefaultManageTokensRepository(
|
|||
val userWallet = request.params.userWalletId?.let(userWalletsListRepository::getSyncStrict)
|
||||
|
||||
if (userWallet is UserWallet.Cold && userWallet.scanResponse.card.isTestCard) {
|
||||
when (val params = request.params) {
|
||||
is ManageTokensListConfig.Account -> fetchTestnetCurrencies(userWallet, params)
|
||||
is ManageTokensListConfig.Wallet -> fetchTestnetCurrenciesLegacy(userWallet, params)
|
||||
}
|
||||
fetchTestnetCurrencies(userWallet, request.params)
|
||||
} else {
|
||||
fetchCurrencies(
|
||||
userWallet = userWallet,
|
||||
|
|
@ -139,24 +126,14 @@ internal class DefaultManageTokensRepository(
|
|||
coins = coinsResponse.coins.filterNot { l2BlockchainsCoinIds.contains(it.id) },
|
||||
)
|
||||
|
||||
val items = when (val params = request.params) {
|
||||
is ManageTokensListConfig.Account -> createManagedCryptoCurrencyList(
|
||||
params = params,
|
||||
userWallet = userWallet,
|
||||
isFirstBatchFetching = isFirstBatchFetching,
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
query = query,
|
||||
updatedCoinsResponse = updatedCoinsResponse,
|
||||
)
|
||||
is ManageTokensListConfig.Wallet -> createManagedCryptoCurrencyListLegacy(
|
||||
params = params,
|
||||
userWallet = userWallet,
|
||||
isFirstBatchFetching = isFirstBatchFetching,
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
query = query,
|
||||
updatedCoinsResponse = updatedCoinsResponse,
|
||||
)
|
||||
}
|
||||
val items = createManagedCryptoCurrencyList(
|
||||
params = request.params,
|
||||
userWallet = userWallet,
|
||||
isFirstBatchFetching = isFirstBatchFetching,
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
query = query,
|
||||
updatedCoinsResponse = updatedCoinsResponse,
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
data = items,
|
||||
|
|
@ -167,7 +144,7 @@ internal class DefaultManageTokensRepository(
|
|||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private suspend fun createManagedCryptoCurrencyList(
|
||||
params: ManageTokensListConfig.Account,
|
||||
params: ManageTokensListConfig,
|
||||
userWallet: UserWallet?,
|
||||
isFirstBatchFetching: Boolean,
|
||||
loadUserTokensFromRemote: Boolean,
|
||||
|
|
@ -238,56 +215,9 @@ internal class DefaultManageTokensRepository(
|
|||
return items
|
||||
}
|
||||
|
||||
private suspend fun createManagedCryptoCurrencyListLegacy(
|
||||
params: ManageTokensListConfig.Wallet,
|
||||
userWallet: UserWallet?,
|
||||
isFirstBatchFetching: Boolean,
|
||||
loadUserTokensFromRemote: Boolean,
|
||||
query: String?,
|
||||
updatedCoinsResponse: CoinsResponse,
|
||||
): List<ManagedCryptoCurrency> {
|
||||
val tokensResponse = params.userWalletId?.let { userWalletId ->
|
||||
if (loadUserTokensFromRemote && userWallet != null) {
|
||||
safeApiCall({ tangemTechApi.getUserTokens(userWalletId.stringValue).bind() }) {
|
||||
// save tokens response only if loadUserTokensFromRemote is true and it means onboarding call
|
||||
createAndSaveDefaultUserTokensResponse(userWallet = userWallet)
|
||||
}
|
||||
} else {
|
||||
getSavedUserTokensResponseSync(userWalletId)
|
||||
}
|
||||
}
|
||||
|
||||
val isCreateWithCustom = isFirstBatchFetching &&
|
||||
tokensResponse != null &&
|
||||
userWallet != null &&
|
||||
query == null
|
||||
|
||||
return if (isCreateWithCustom) {
|
||||
managedCryptoCurrencyFactory.createWithCustomTokens(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
} else {
|
||||
managedCryptoCurrencyFactory.create(
|
||||
coinsResponse = updatedCoinsResponse,
|
||||
tokensResponse = tokensResponse,
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun createAndSaveDefaultUserTokensResponse(userWallet: UserWallet): UserTokensResponse {
|
||||
val userTokensResponse = createDefaultUserTokensResponse(userWallet)
|
||||
userTokenSaver.store(userWallet.walletId, userTokensResponse, useEnricher = false)
|
||||
return userTokensResponse
|
||||
}
|
||||
|
||||
private suspend fun fetchTestnetCurrencies(
|
||||
userWallet: UserWallet,
|
||||
params: ManageTokensListConfig.Account,
|
||||
params: ManageTokensListConfig,
|
||||
): BatchFetchResult.Success<List<ManagedCryptoCurrency>> {
|
||||
val searchText = params.searchText
|
||||
val testnetTokensConfig = testnetTokensStorage.getConfig()
|
||||
|
|
@ -342,45 +272,6 @@ internal class DefaultManageTokensRepository(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun fetchTestnetCurrenciesLegacy(
|
||||
userWallet: UserWallet,
|
||||
params: ManageTokensListConfig.Wallet,
|
||||
): BatchFetchResult.Success<List<ManagedCryptoCurrency>> {
|
||||
val searchText = params.searchText
|
||||
val testnetTokensConfig = testnetTokensStorage.getConfig()
|
||||
|
||||
val items = managedCryptoCurrencyFactory.createTestnetWithCustomTokens(
|
||||
testnetTokensConfig = if (!searchText.isNullOrBlank()) {
|
||||
testnetTokensConfig.copy(
|
||||
tokens = testnetTokensConfig.tokens.filter { token ->
|
||||
token.symbol.contains(other = searchText, ignoreCase = true) ||
|
||||
token.name.contains(other = searchText, ignoreCase = true)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
testnetTokensConfig
|
||||
},
|
||||
tokensResponse = getSavedUserTokensResponseSync(userWallet.walletId),
|
||||
userWallet = userWallet,
|
||||
accountIndex = DerivationIndex.Main,
|
||||
)
|
||||
|
||||
return BatchFetchResult.Success(
|
||||
data = items,
|
||||
empty = items.isEmpty(),
|
||||
last = true,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createDefaultUserTokensResponse(userWallet: UserWallet) =
|
||||
userTokensResponseFactory.createUserTokensResponse(
|
||||
currencies = cardCryptoCurrencyFactory.createDefaultCoinsForMultiCurrencyWallet(
|
||||
userWallet = userWallet,
|
||||
),
|
||||
isGroupedByNetwork = false,
|
||||
isSortedByBalance = false,
|
||||
)
|
||||
|
||||
private fun getSupportedBlockchains(userWallet: UserWallet?): List<Blockchain> {
|
||||
return userWallet?.supportedBlockchains(excludedBlockchains)
|
||||
?: Blockchain.entries.filter {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@ package com.tangem.data.managetokens.di
|
|||
|
||||
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
|
||||
import com.tangem.data.common.account.WalletAccountsFetcher
|
||||
import com.tangem.data.common.currency.CardCryptoCurrencyFactory
|
||||
import com.tangem.data.common.currency.UserTokensSaver
|
||||
import com.tangem.data.common.network.NetworkFactory
|
||||
import com.tangem.data.managetokens.DefaultCustomTokensRepository
|
||||
import com.tangem.data.managetokens.DefaultManageTokensRepository
|
||||
|
|
@ -11,7 +9,6 @@ import com.tangem.data.managetokens.utils.ManageTokensUpdateFetcher
|
|||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
import com.tangem.datasource.local.config.testnet.TestnetTokensStorage
|
||||
import com.tangem.datasource.local.token.UserTokensResponseStore
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.managetokens.repository.CustomTokensRepository
|
||||
import com.tangem.domain.managetokens.repository.ManageTokensRepository
|
||||
|
|
@ -33,13 +30,10 @@ internal object ManageTokensDataModule {
|
|||
userWalletsListRepository: UserWalletsListRepository,
|
||||
manageTokensUpdateFetcher: ManageTokensUpdateFetcher,
|
||||
userTokensResponseStore: UserTokensResponseStore,
|
||||
userTokensSaver: UserTokensSaver,
|
||||
testnetTokensStorage: TestnetTokensStorage,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
excludedBlockchains: ExcludedBlockchains,
|
||||
cardCryptoCurrencyFactory: CardCryptoCurrencyFactory,
|
||||
networkFactory: NetworkFactory,
|
||||
accountsFeatureToggles: AccountsFeatureToggles,
|
||||
walletAccountsFetcher: WalletAccountsFetcher,
|
||||
): ManageTokensRepository {
|
||||
return DefaultManageTokensRepository(
|
||||
|
|
@ -47,13 +41,10 @@ internal object ManageTokensDataModule {
|
|||
userWalletsListRepository = userWalletsListRepository,
|
||||
manageTokensUpdateFetcher = manageTokensUpdateFetcher,
|
||||
userTokensResponseStore = userTokensResponseStore,
|
||||
userTokenSaver = userTokensSaver,
|
||||
testnetTokensStorage = testnetTokensStorage,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
cardCryptoCurrencyFactory = cardCryptoCurrencyFactory,
|
||||
networkFactory = networkFactory,
|
||||
dispatchers = dispatchers,
|
||||
accountsFeatureToggles = accountsFeatureToggles,
|
||||
walletAccountsFetcher = walletAccountsFetcher,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import com.tangem.data.common.network.NetworkFactory
|
|||
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
|
||||
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
||||
import com.tangem.datasource.local.config.testnet.models.TestnetTokensConfig
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.card.common.extensions.canHandleToken
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency
|
||||
import com.tangem.domain.managetokens.model.ManagedCryptoCurrency.SourceNetwork
|
||||
|
|
@ -21,7 +20,6 @@ import com.tangem.domain.models.account.DerivationIndex
|
|||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.derivations.DerivationStyleProvider
|
||||
import com.tangem.domain.wallets.derivations.derivationStyleProvider
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import timber.log.Timber
|
||||
|
|
@ -29,7 +27,6 @@ import timber.log.Timber
|
|||
internal class ManagedCryptoCurrencyFactory(
|
||||
private val networkFactory: NetworkFactory,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) {
|
||||
|
||||
fun create(
|
||||
|
|
@ -120,30 +117,15 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
?.takeUnless { it in excludedBlockchains }
|
||||
?: return null
|
||||
|
||||
val network = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
val network = networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
|
||||
if (!checkIsCustomToken(token, network.derivationPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
network
|
||||
} else {
|
||||
if (!checkIsCustomToken(token, blockchain, userWallet.derivationStyleProvider)) {
|
||||
return null
|
||||
}
|
||||
|
||||
networkFactory.create(
|
||||
blockchain = blockchain,
|
||||
extraDerivationPath = token.derivationPath,
|
||||
userWallet = userWallet,
|
||||
accountIndex = accountIndex,
|
||||
) ?: return null
|
||||
if (!checkIsCustomToken(token, network.derivationPath)) {
|
||||
return null
|
||||
}
|
||||
|
||||
val contractAddress = token.contractAddress
|
||||
|
|
@ -285,23 +267,10 @@ internal class ManagedCryptoCurrencyFactory(
|
|||
return "${imageHost ?: DEFAULT_IMAGE_HOST}large/$id.png"
|
||||
}
|
||||
|
||||
private fun checkIsCustomToken(
|
||||
token: UserTokensResponse.Token,
|
||||
blockchain: Blockchain,
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
): Boolean = token.id.isNullOrBlank() ||
|
||||
checkIsCustomDerivationPath(token.derivationPath, blockchain, derivationStyleProvider)
|
||||
|
||||
private fun checkIsCustomToken(token: UserTokensResponse.Token, derivationPath: Network.DerivationPath): Boolean {
|
||||
return token.id.isNullOrBlank() || derivationPath is Network.DerivationPath.Custom
|
||||
}
|
||||
|
||||
private fun checkIsCustomDerivationPath(
|
||||
derivationPath: String?,
|
||||
blockchain: Blockchain,
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
): Boolean = derivationPath != blockchain.derivationPath(derivationStyleProvider.getDerivationStyle())?.rawPath
|
||||
|
||||
/**
|
||||
* Filter tokens for TerraV1 (Terra Classic) network.
|
||||
* Only native coin (LUNC) and TerraClassicUSD (USTC) are allowed.
|
||||
|
|
|
|||
|
|
@ -3,24 +3,10 @@ package com.tangem.domain.managetokens.model
|
|||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
||||
sealed interface ManageTokensListConfig {
|
||||
|
||||
data class ManageTokensListConfig(
|
||||
val accountId: AccountId?,
|
||||
val searchText: String?,
|
||||
) {
|
||||
val userWalletId: UserWalletId?
|
||||
val searchText: String?
|
||||
|
||||
// old way
|
||||
data class Wallet(
|
||||
override val userWalletId: UserWalletId?,
|
||||
override val searchText: String?,
|
||||
) : ManageTokensListConfig
|
||||
|
||||
// new way
|
||||
data class Account(
|
||||
val accountId: AccountId?,
|
||||
override val searchText: String?,
|
||||
) : ManageTokensListConfig {
|
||||
|
||||
override val userWalletId: UserWalletId?
|
||||
get() = accountId?.userWalletId
|
||||
}
|
||||
get() = accountId?.userWalletId
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ import com.tangem.domain.account.models.AccountList
|
|||
import com.tangem.domain.account.usecase.AddCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.usecase.GetUnoccupiedAccountIndexUseCase
|
||||
import com.tangem.domain.account.usecase.UpdateCryptoPortfolioUseCase
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.CryptoPortfolioIcon
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
|
|
@ -141,7 +140,7 @@ internal class AccountCreateEditModel @Inject constructor(
|
|||
showMessage(R.string.account_create_success_message)
|
||||
val route = AppRoute.ManageTokens(
|
||||
source = AppRoute.ManageTokens.Source.ACCOUNT,
|
||||
portfolioId = PortfolioId(account.accountId),
|
||||
accountId = account.accountId,
|
||||
)
|
||||
router.replaceCurrent(route)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import com.tangem.core.ui.message.EventMessageAction
|
|||
import com.tangem.core.ui.message.ToastMessage
|
||||
import com.tangem.domain.account.status.usecase.ArchiveCryptoPortfolioUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.wallet.isMultiCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
|
|
@ -65,7 +64,7 @@ internal class AccountDetailsModel @Inject constructor(
|
|||
private fun onManageTokensClick(account: Account.CryptoPortfolio) {
|
||||
val route = AppRoute.ManageTokens(
|
||||
source = AppRoute.ManageTokens.Source.ACCOUNT,
|
||||
portfolioId = PortfolioId(account.accountId),
|
||||
accountId = account.accountId,
|
||||
)
|
||||
analyticsEventHandler.send(
|
||||
AccountSettingsAnalyticEvents.ButtonManageTokens(account.derivationIndex.value),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.serialization)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.features.managetokens.component
|
|||
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
enum class ManageTokensSource(val analyticsName: String) {
|
||||
STORIES(analyticsName = "Stories"),
|
||||
|
|
@ -12,18 +13,15 @@ enum class ManageTokensSource(val analyticsName: String) {
|
|||
}
|
||||
|
||||
sealed interface ManageTokensMode {
|
||||
data class Wallet(val userWalletId: UserWalletId) : ManageTokensMode
|
||||
data class Account(val accountId: AccountId) : ManageTokensMode
|
||||
data class Account(val accountId: AccountId) : ManageTokensMode {
|
||||
constructor(userWalletId: UserWalletId) : this(AccountId.forMainCryptoPortfolio(userWalletId))
|
||||
}
|
||||
data object None : ManageTokensMode
|
||||
}
|
||||
|
||||
sealed interface AddCustomTokenMode {
|
||||
@Serializable
|
||||
data class AddCustomTokenMode(val accountId: AccountId) {
|
||||
val userWalletId: UserWalletId = accountId.userWalletId
|
||||
|
||||
val userWalletId: UserWalletId
|
||||
|
||||
data class Wallet(override val userWalletId: UserWalletId) : AddCustomTokenMode
|
||||
|
||||
data class Account(val accountId: AccountId) : AddCustomTokenMode {
|
||||
override val userWalletId: UserWalletId = accountId.userWalletId
|
||||
}
|
||||
constructor(userWalletId: UserWalletId) : this(AccountId.forMainCryptoPortfolio(userWalletId))
|
||||
}
|
||||
|
|
@ -4,47 +4,21 @@
|
|||
<CurrentIssues>
|
||||
<ID>BooleanPropertyNaming:AddCustomTokenUM.kt$AddCustomTokenUM$val showBackButton: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:CustomCurrencyValidator.kt$CustomCurrencyValidator.Status.Validated$val fillForm: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:CustomTokenFormModel.kt$CustomTokenFormModel$val needColdWalletInteraction = coldWalletAndHasMissedDerivationsUseCase.invoke( userWalletId = params.mode.userWalletId, networksWithDerivationPath = mapOf(currency.network.backendId to getDerivationPath().value), )</ID>
|
||||
<ID>BooleanPropertyNaming:ManageTokensListManager.kt$ManageTokensListManager$val loadUserTokensFromRemote = when (mode) { is ManageTokensMode.Wallet, is ManageTokensMode.Account, -> source == ManageTokensSource.ONBOARDING ManageTokensMode.None, -> false }</ID>
|
||||
<ID>BooleanPropertyNaming:ManageTokensModel.kt$ManageTokensModel$val needToInteractWithColdWallet = useCasesFacade.needColdWalletInteraction(networks)</ID>
|
||||
<ID>BooleanPropertyNaming:ManageTokensUM.kt$ManageTokensUM.ManageContent$val needToInteractWithColdWallet: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:OnboardingManageTokensModel.kt$OnboardingManageTokensModel$val showTangemIcon = useCasesFacade.needColdWalletInteraction(network = network)</ID>
|
||||
<ID>BooleanPropertyNaming:OnboardingManageTokensUM.kt$OnboardingManageTokensUM.ActionButtonConfig$abstract val showProgress: Boolean</ID>
|
||||
<ID>BooleanPropertyNaming:OnboardingManageTokensUM.kt$OnboardingManageTokensUM.ActionButtonConfig.Continue$val showTangemIcon: Boolean</ID>
|
||||
<ID>MaxChainedCallsOnSameLine:ChooseManagedTokensModel.kt$ChooseManagedTokensModel$params.initialCurrency.network.id.rawId.value</ID>
|
||||
<ID>MultilineLambdaItParameter:ChooseManagedTokenContent.kt${ add( CurrencyItemUM.Basic( id = ManagedCryptoCurrency.ID( value = "ID+$it", ), name = "Bitcoin", symbol = "BTC", icon = CurrencyIconState.Loading, networks = CurrencyItemUM.Basic.NetworksUM.Collapsed, onExpandClick = {}, ), ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:ChooseManagedTokensModel.kt$ChooseManagedTokensModel${ it.copy( notificationUM = null, ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CurrencyItemMapper.kt${ it.toCurrencyNetworkModel( isSelected = it.network in addedIn, isEditable = false, onSelectedStateChange = { _, _ -> }, onLongTap = { _ -> }, ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomCurrencyFormOperations.kt${ it[Field.CONTRACT_ADDRESS] = it.getValue(Field.CONTRACT_ADDRESS).copy( error = when (exception) { CustomTokenFormValidationException.ContractAddress.Invalid -> { resourceReference(R.string.custom_token_creation_error_invalid_contract_address) } }, ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomCurrencyFormOperations.kt${ it[Field.DECIMALS] = it.getValue(Field.DECIMALS).copy( error = when (exception) { is CustomTokenFormValidationException.Decimals.Empty -> { null // Should not display this error } is CustomTokenFormValidationException.Decimals.Invalid -> { resourceReference( R.string.custom_token_creation_error_wrong_decimals, wrappedList(ValidateTokenFormUseCase.MAX_DECIMALS), ) } }, ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomTokenFormContent.kt$PreviewCustomTokenFormComponentProvider${ it[Field.CONTRACT_ADDRESS] = it[Field.CONTRACT_ADDRESS]!!.copy( label = stringReference("Contract address"), value = "0x1234567890", error = stringReference("Contract address is invalid"), placeholder = stringReference("0x1234567890"), ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomTokenFormContent.kt$PreviewCustomTokenFormComponentProvider${ it[Field.CONTRACT_ADDRESS] = it[Field.CONTRACT_ADDRESS]!!.copy( label = stringReference("Contract address"), value = "0x1234567890", placeholder = stringReference("0x1234567890"), ) }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomTokenFormModel.kt$CustomTokenFormModel${ Timber.e(it, "Failed to add currency") showErrorDialog() return@resource }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomTokenFormModel.kt$CustomTokenFormModel${ Timber.e(it, "Failed to derive public keys") showErrorDialog() return@resource }</ID>
|
||||
<ID>MultilineLambdaItParameter:CustomTokenSelectorModel.kt$CustomTokenSelectorModel${ when (it) { is AccountStatus.CryptoPortfolio -> it.sameNodeAndNotMain() } }</ID>
|
||||
<ID>MultilineLambdaItParameter:ManageTokensListManager.kt$ManageTokensListManager${ Timber.e( it, """ Failed to check currency unsupported state |- Mode: $mode |- Source Network: $sourceNetwork """.trimIndent(), ) val message = SnackbarMessage( message = it.localizedMessage ?.let(::stringReference) ?: resourceReference(R.string.common_error), ) messageSender.send(message) null }</ID>
|
||||
<ID>MultilineLambdaItParameter:ManageTokensListManager.kt$ManageTokensListManager${ Timber.e( it, """ Failed to check linked tokens |- Mode: $mode |- Network ID: ${network.id} """.trimIndent(), ) val message = SnackbarMessage( message = it.localizedMessage ?.let(::stringReference) ?: resourceReference(R.string.common_error), ) messageSender.send(message) false }</ID>
|
||||
<ID>MultilineLambdaItParameter:ManageTokensModel.kt$ManageTokensModel${ Timber.e(it, "Failed to save changes") return@resource }</ID>
|
||||
<ID>MultilineLambdaItParameter:ManageTokensUseCasesFacade.kt$ManageTokensUseCasesFacade${ it is CryptoCurrency.Token && it.network.backendId == network.backendId && it.network.derivationPath == network.derivationPath }</ID>
|
||||
<ID>MultilineLambdaItParameter:OnboardingManageTokensModel.kt$OnboardingManageTokensModel${ Timber.e(it, "Failed to save changes") return@resource }</ID>
|
||||
<ID>MultilineLambdaItParameter:PreviewManageTokensComponent.kt$PreviewManageTokensComponent${ it.fastForEachIndexed { index, network -> if (index == networkIndex) { it[index] = network.copy( iconResId = if (isSelected) { R.drawable.img_eth_22 } else { R.drawable.ic_eth_16 }, isSelected = isSelected, ) } } }</ID>
|
||||
<ID>NamedArguments:ChangedCurrenciesManager.kt$ChangedCurrenciesManager$updateChangedItems(currency, network, currenciesToAdd, currenciesToRemove)</ID>
|
||||
<ID>NamedArguments:ChangedCurrenciesManager.kt$ChangedCurrenciesManager$updateChangedItems(currency, network, currenciesToRemove, currenciesToAdd)</ID>
|
||||
<ID>NamedArguments:ChooseManagedTokensModel.kt$ChooseManagedTokensModel$TokenSearched( params.analyticsCategoryName, token = null, blockchain = null, isTokenChosen = false, )</ID>
|
||||
<ID>NamedArguments:ManageTokensListManager.kt$ManageTokensListManager$selectNetwork(currencyBatch.key, currency, networkId, isSelected)</ID>
|
||||
<ID>NamedArguments:ManageTokensListManager.kt$ManageTokensListManager$sendSelectCurrencyAction(batchKey, currency.id, network, isSelected = false)</ID>
|
||||
<ID>NamedArguments:ManageTokensListManager.kt$ManageTokensListManager$sendSelectCurrencyAction(batchKey, currency.id, network, isSelected = true)</ID>
|
||||
<ID>NestedScopeFunctions:CustomTokenSelectorModel.kt$CustomTokenSelectorModel$let { recognizer.recognize(it) }</ID>
|
||||
<ID>NullableBooleanCheck:CustomCurrencyFormOperations.kt$this.tokenForm?.wasFilled ?: false</ID>
|
||||
<ID>PropertyUsedBeforeDeclaration:ChooseManagedTokensModel.kt$ChooseManagedTokensModel$bottomSheetNavigation</ID>
|
||||
<ID>PropertyUsedBeforeDeclaration:ChooseManagedTokensModel.kt$ChooseManagedTokensModel$uiState</ID>
|
||||
<ID>UnsafeCallOnNullableType:CustomTokenFormContent.kt$PreviewCustomTokenFormComponentProvider$it[Field.CONTRACT_ADDRESS]!!</ID>
|
||||
<ID>UnsafeCallOnNullableType:PreviewAddCustomTokenComponent.kt$PreviewAddCustomTokenComponent$config.selectedDerivationPath!!</ID>
|
||||
<ID>UnsafeCallOnNullableType:PreviewAddCustomTokenComponent.kt$PreviewAddCustomTokenComponent$config.selectedNetwork!!</ID>
|
||||
<ID>UseEmptyCounterpart:CustomTokenAnalyticsEvent.kt$CustomTokenAnalyticsEvent$mapOf()</ID>
|
||||
<ID>UseEmptyCounterpart:ManageTokensAnalyticEvent.kt$ManageTokensAnalyticEvent$mapOf()</ID>
|
||||
<ID>UseOrEmpty:ChangedCurrenciesManager.kt$ChangedCurrenciesManager$items[currency] ?: emptySet()</ID>
|
||||
<ID>UseOrEmpty:PreviewCustomTokenSelectorComponent.kt$PreviewCustomTokenSelectorComponent$d.id?.rawId?.value ?: ""</ID>
|
||||
<ID>VarCouldBeVal:CustomTokenFormModel.kt$CustomTokenFormModel$private var useCasesFacade: CustomTokenFormUseCasesFacade = customTokenFormUseCasesFacadeFactory.create(params.mode)</ID>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ import com.tangem.core.ui.event.triggeredEvent
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.notifications.SetShouldShowNotificationUseCase
|
||||
import com.tangem.features.managetokens.choosetoken.entity.ChooseManageTokensBottomSheetConfig
|
||||
import com.tangem.features.managetokens.choosetoken.entity.ChooseManagedTokenUM
|
||||
|
|
@ -45,7 +43,6 @@ import kotlinx.coroutines.flow.*
|
|||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.isNotEmpty
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
|
|
@ -55,7 +52,6 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
private val uiMessageSender: UiMessageSender,
|
||||
private val setShouldShowNotificationUseCase: SetShouldShowNotificationUseCase,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
accountsFeatureToggles: AccountsFeatureToggles,
|
||||
paramsContainer: ParamsContainer,
|
||||
manageTokensUseCasesFacadeFactory: ManageTokensUseCasesFacade.Factory,
|
||||
manageTokensListManagerFactory: ManageTokensListManager.Factory,
|
||||
|
|
@ -63,16 +59,15 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
|
||||
private val params: ChooseManagedTokensComponent.Params = paramsContainer.require()
|
||||
|
||||
private val manageTokensMode = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
val accountId = AccountId.forMainCryptoPortfolio(userWalletId = params.userWalletId)
|
||||
ManageTokensMode.Account(accountId = accountId)
|
||||
} else {
|
||||
ManageTokensMode.Wallet(params.userWalletId)
|
||||
}
|
||||
private val manageTokensMode = ManageTokensMode.Account(params.userWalletId)
|
||||
|
||||
private val useCasesFacade: ManageTokensUseCasesFacade = manageTokensUseCasesFacadeFactory
|
||||
.create(mode = manageTokensMode)
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<ChooseManageTokensBottomSheetConfig> = SlotNavigation()
|
||||
val uiState: StateFlow<ChooseManagedTokenUM>
|
||||
field = MutableStateFlow<ChooseManagedTokenUM>(createReadContentModel())
|
||||
|
||||
private val manageTokensListManager = manageTokensListManagerFactory.create(
|
||||
scope = modelScope,
|
||||
source = ManageTokensSource.SEND_VIA_SWAP,
|
||||
|
|
@ -91,10 +86,6 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
},
|
||||
)
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<ChooseManageTokensBottomSheetConfig> = SlotNavigation()
|
||||
val uiState: StateFlow<ChooseManagedTokenUM>
|
||||
field = MutableStateFlow<ChooseManagedTokenUM>(createReadContentModel())
|
||||
|
||||
init {
|
||||
manageTokensListManager.uiItems
|
||||
.onEach { items -> updateItems(items) }
|
||||
|
|
@ -146,11 +137,7 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
private fun removeNotification() {
|
||||
modelScope.launch {
|
||||
setShouldShowNotificationUseCase(NotificationId.SendViaSwapTokenSelectorNotification.key, false)
|
||||
uiState.update {
|
||||
it.copy(
|
||||
notificationUM = null,
|
||||
)
|
||||
}
|
||||
uiState.update { it.copy(notificationUM = null) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,7 +148,7 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
if (!new.readContent.search.isActive && old.readContent.search.isActive) {
|
||||
analyticsEventHandler.send(
|
||||
CommonManageTokensAnalyticEvents.TokenSearched(
|
||||
params.analyticsCategoryName,
|
||||
categoryName = params.analyticsCategoryName,
|
||||
token = null,
|
||||
blockchain = null,
|
||||
isTokenChosen = false,
|
||||
|
|
@ -195,8 +182,9 @@ internal class ChooseManagedTokensModel @Inject constructor(
|
|||
val isToken = currency.id.value == params.initialCurrency.id.rawCurrencyId?.value
|
||||
|
||||
// Ensure that initial token network is filtered out and network list is empty
|
||||
val paramsRawId = params.initialCurrency.network.id.rawId
|
||||
val isEmptyNetworks = availableNetworks?.networks?.filterNot { network ->
|
||||
network.id == params.initialCurrency.network.id.rawId.value
|
||||
network.id == paramsRawId.value
|
||||
}.isNullOrEmpty()
|
||||
|
||||
// Filter out currency from display
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.wrappedList
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.AccountName
|
||||
import com.tangem.features.managetokens.component.AddCustomTokenComponent
|
||||
import com.tangem.features.managetokens.component.AddCustomTokenMode
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensBottomSheetConfig
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
import com.tangem.features.managetokens.model.ManageTokensModel
|
||||
import com.tangem.features.managetokens.ui.ManageTokensScreen
|
||||
|
|
@ -38,7 +38,7 @@ internal class DefaultManageTokensComponent @AssistedInject constructor(
|
|||
|
||||
private val bottomSheetSlot = childSlot(
|
||||
source = model.bottomSheetNavigation,
|
||||
serializer = ManageTokensBottomSheetConfig.serializer(),
|
||||
serializer = AccountId.serializer(),
|
||||
handleBackButton = false,
|
||||
childFactory = ::bottomSheetChild,
|
||||
)
|
||||
|
|
@ -57,13 +57,10 @@ internal class DefaultManageTokensComponent @AssistedInject constructor(
|
|||
}
|
||||
|
||||
private fun bottomSheetChild(
|
||||
config: ManageTokensBottomSheetConfig,
|
||||
accountId: AccountId,
|
||||
componentContext: ComponentContext,
|
||||
): ComposableBottomSheetComponent {
|
||||
val mode = when (config) {
|
||||
is ManageTokensBottomSheetConfig.AddWalletCustomToken -> AddCustomTokenMode.Wallet(config.userWalletId)
|
||||
is ManageTokensBottomSheetConfig.AddAccountCustomToken -> AddCustomTokenMode.Account(config.accountId)
|
||||
}
|
||||
val mode = AddCustomTokenMode(accountId)
|
||||
return addCustomTokenComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = AddCustomTokenComponent.Params(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
|
||||
internal class PreviewAddCustomTokenComponent(
|
||||
initialState: AddCustomTokenConfig = AddCustomTokenConfig(
|
||||
mode = AddCustomTokenMode.Wallet(UserWalletId(stringValue = "321")),
|
||||
mode = AddCustomTokenMode(UserWalletId(stringValue = "321")),
|
||||
step = AddCustomTokenConfig.Step.INITIAL_NETWORK_SELECTOR,
|
||||
),
|
||||
) : AddCustomTokenComponent {
|
||||
|
|
@ -61,8 +61,8 @@ internal class PreviewAddCustomTokenComponent(
|
|||
PreviewCustomTokenSelectorComponent(
|
||||
params = CustomTokenSelectorComponent.Params.DerivationPathSelector(
|
||||
mode = config.mode,
|
||||
selectedNetwork = config.selectedNetwork!!,
|
||||
selectedDerivationPath = config.selectedDerivationPath!!,
|
||||
selectedNetwork = requireNotNull(config.selectedNetwork),
|
||||
selectedDerivationPath = requireNotNull(config.selectedDerivationPath),
|
||||
onDerivationPathSelected = { _, _ -> },
|
||||
),
|
||||
).Content(modifier)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import kotlinx.collections.immutable.toImmutableList
|
|||
|
||||
internal class PreviewCustomTokenSelectorComponent(
|
||||
private val params: Params = Params.NetworkSelector(
|
||||
mode = AddCustomTokenMode.Wallet(UserWalletId(stringValue = "321")),
|
||||
mode = AddCustomTokenMode(UserWalletId(stringValue = "321")),
|
||||
selectedNetwork = null,
|
||||
onNetworkSelected = {},
|
||||
),
|
||||
|
|
@ -39,7 +39,7 @@ internal class PreviewCustomTokenSelectorComponent(
|
|||
)
|
||||
|
||||
DerivationPathUM(
|
||||
id = d.id?.rawId?.value ?: "",
|
||||
id = d.id?.rawId?.value.orEmpty(),
|
||||
value = d.value.value.orEmpty(),
|
||||
networkName = stringReference(d.name),
|
||||
isSelected = d.value == params.selectedDerivationPath?.value,
|
||||
|
|
|
|||
|
|
@ -40,9 +40,7 @@ internal class PreviewManageTokensComponent(
|
|||
popBack = {},
|
||||
items = items,
|
||||
topBar = when (params.mode) {
|
||||
is ManageTokensMode.Account,
|
||||
is ManageTokensMode.Wallet,
|
||||
-> ManageTokensTopBarUM.ManageContent(
|
||||
is ManageTokensMode.Account -> ManageTokensTopBarUM.ManageContent(
|
||||
title = resourceReference(id = R.string.main_manage_tokens),
|
||||
onBackButtonClick = {},
|
||||
endButton = TopAppBarButtonUM.Icon(
|
||||
|
|
@ -206,10 +204,10 @@ internal class PreviewManageTokensComponent(
|
|||
is CurrencyItemUM.Basic -> {
|
||||
val updatedNetworks = (item.networks as? CurrencyItemUM.Basic.NetworksUM.Expanded)
|
||||
?.copy(
|
||||
networks = item.networks.networks.toPersistentList().mutate {
|
||||
it.fastForEachIndexed { index, network ->
|
||||
networks = item.networks.networks.toPersistentList().mutate { networks ->
|
||||
networks.fastForEachIndexed { index, network ->
|
||||
if (index == networkIndex) {
|
||||
it[index] = network.copy(
|
||||
networks[index] = network.copy(
|
||||
iconResId = if (isSelected) {
|
||||
R.drawable.img_eth_22
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package com.tangem.features.managetokens.entity.managetokens
|
||||
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
internal sealed class ManageTokensBottomSheetConfig {
|
||||
|
||||
@Serializable
|
||||
data class AddWalletCustomToken(
|
||||
val userWalletId: UserWalletId,
|
||||
) : ManageTokensBottomSheetConfig()
|
||||
|
||||
@Serializable
|
||||
data class AddAccountCustomToken(
|
||||
val accountId: AccountId,
|
||||
) : ManageTokensBottomSheetConfig()
|
||||
}
|
||||
|
|
@ -179,7 +179,7 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
isAlreadyAdded: Boolean,
|
||||
isCustom: Boolean,
|
||||
) = modelScope.launch {
|
||||
val needColdWalletInteraction = coldWalletAndHasMissedDerivationsUseCase.invoke(
|
||||
val isNeedColdWalletInteraction = coldWalletAndHasMissedDerivationsUseCase.invoke(
|
||||
userWalletId = params.mode.userWalletId,
|
||||
networksWithDerivationPath = mapOf(currency.network.backendId to getDerivationPath().value),
|
||||
)
|
||||
|
|
@ -193,7 +193,7 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
clearNotifications = true,
|
||||
clearFieldErrors = true,
|
||||
disableSecondaryFields = !isCustom,
|
||||
walletInteractionIcon = R.drawable.ic_tangem_24.takeIf { needColdWalletInteraction },
|
||||
walletInteractionIcon = R.drawable.ic_tangem_24.takeIf { isNeedColdWalletInteraction },
|
||||
)
|
||||
|
||||
if (fillForm) {
|
||||
|
|
@ -353,14 +353,8 @@ internal class CustomTokenFormModel @Inject constructor(
|
|||
)
|
||||
analyticsEventHandler.send(event)
|
||||
|
||||
useCasesFacade.derivePublicKeysUseCase(listOf(currency)).getOrElse {
|
||||
Timber.e(it, "Failed to derive public keys")
|
||||
showErrorDialog()
|
||||
return@resource
|
||||
}
|
||||
|
||||
useCasesFacade.addCryptoCurrenciesUseCase(currency).getOrElse {
|
||||
Timber.e(it, "Failed to add currency")
|
||||
useCasesFacade.addCryptoCurrenciesUseCase(currency).getOrElse { throwable ->
|
||||
Timber.e(throwable, "Failed to add currency")
|
||||
showErrorDialog()
|
||||
return@resource
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import com.tangem.core.ui.extensions.wrappedList
|
|||
import com.tangem.core.ui.message.DialogMessage
|
||||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.managetokens.GetSupportedNetworksUseCase
|
||||
import com.tangem.domain.models.account.Account
|
||||
|
|
@ -52,7 +51,6 @@ internal class CustomTokenSelectorModel @Inject constructor(
|
|||
private val getSupportedNetworksUseCase: GetSupportedNetworksUseCase,
|
||||
private val messageSender: UiMessageSender,
|
||||
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -171,7 +169,7 @@ internal class CustomTokenSelectorModel @Inject constructor(
|
|||
}
|
||||
|
||||
private suspend fun getSupportedNetworks(mode: AddCustomTokenMode): List<Network> {
|
||||
return getSupportedNetworksUseCase(mode.userWalletId).getOrElse { e ->
|
||||
return getSupportedNetworksUseCase(mode.userWalletId).getOrElse { _ ->
|
||||
val message = SnackbarMessage(message = resourceReference(R.string.common_unknown_error))
|
||||
messageSender.send(message)
|
||||
|
||||
|
|
@ -194,19 +192,23 @@ internal class CustomTokenSelectorModel @Inject constructor(
|
|||
fun selectCustomDerivationPath(value: SelectedDerivationPath) {
|
||||
when (params) {
|
||||
is NetworkSelector -> return
|
||||
is DerivationPathSelector -> if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
params.checkAccountDerivation(value)
|
||||
} else {
|
||||
params.onDerivationPathSelected(value, null)
|
||||
}
|
||||
is DerivationPathSelector -> params.checkAccountDerivation(value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DerivationPathSelector.checkAccountDerivation(derivationPath: SelectedDerivationPath) =
|
||||
modelScope.launch {
|
||||
val account = derivationPath.id
|
||||
?.let { Blockchain.fromId(it.rawId.value) }?.let(::AccountNodeRecognizer)
|
||||
?.let { recognizer -> derivationPath.value.value?.let { recognizer.recognize(it) } }
|
||||
?.let { Blockchain.fromId(it.rawId.value) }
|
||||
?.let(::AccountNodeRecognizer)
|
||||
?.let { recognizer ->
|
||||
val derivationPathValue = derivationPath.value.value
|
||||
if (derivationPathValue != null) {
|
||||
recognizer.recognize(derivationPathValue)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
?.let { accountNode ->
|
||||
fun AccountStatus.CryptoPortfolio.sameNodeAndNotMain() = !this.account.isMainAccount &&
|
||||
this.account.derivationIndex.value.toLong() == accountNode
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@ import com.tangem.core.ui.extensions.resourceReference
|
|||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.account.status.supplier.SingleAccountStatusListSupplier
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.features.managetokens.analytics.CustomTokenAnalyticsEvent
|
||||
import com.tangem.features.managetokens.analytics.ManageTokensAnalyticEvent
|
||||
import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||
import com.tangem.features.managetokens.component.ManageTokensMode
|
||||
import com.tangem.features.managetokens.entity.item.CurrencyItemUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensBottomSheetConfig
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensTopBarUM
|
||||
import com.tangem.features.managetokens.entity.managetokens.ManageTokensUM
|
||||
import com.tangem.features.managetokens.impl.R
|
||||
|
|
@ -66,7 +66,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
)
|
||||
|
||||
val state: MutableStateFlow<ManageTokensUM> = MutableStateFlow(getInitialState())
|
||||
val bottomSheetNavigation: SlotNavigation<ManageTokensBottomSheetConfig> = SlotNavigation()
|
||||
val bottomSheetNavigation: SlotNavigation<AccountId> = SlotNavigation()
|
||||
|
||||
init {
|
||||
manageTokensListManager.uiItems
|
||||
|
|
@ -101,15 +101,12 @@ internal class ManageTokensModel @Inject constructor(
|
|||
analyticsEventHandler.send(ManageTokensAnalyticEvent.ScreenOpened(params.source))
|
||||
|
||||
return when (params.mode) {
|
||||
is ManageTokensMode.Wallet,
|
||||
is ManageTokensMode.Account,
|
||||
-> createManageContentModel()
|
||||
is ManageTokensMode.Account -> createManageContentModel()
|
||||
ManageTokensMode.None -> createReadContentModel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTopBarInitialState(): ManageTokensTopBarUM = when (params.mode) {
|
||||
is ManageTokensMode.Wallet -> manageContentTopBar()
|
||||
is ManageTokensMode.Account -> ManageTokensTopBarUM.ReadContent(
|
||||
title = resourceReference(id = R.string.main_manage_tokens),
|
||||
onBackButtonClick = router::pop,
|
||||
|
|
@ -196,9 +193,7 @@ internal class ManageTokensModel @Inject constructor(
|
|||
state.update { it.copySealed(topBar = manageContentTopBar()) }
|
||||
}
|
||||
}
|
||||
ManageTokensMode.None,
|
||||
is ManageTokensMode.Wallet,
|
||||
-> Unit // use init state
|
||||
ManageTokensMode.None -> Unit // use init state
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -299,12 +294,12 @@ internal class ManageTokensModel @Inject constructor(
|
|||
.flatten()
|
||||
.toSet()
|
||||
.associate { network -> network.backendId to network.derivationPath.value }
|
||||
val needToInteractWithColdWallet = useCasesFacade.needColdWalletInteraction(networks)
|
||||
val isNeedToInteractWithColdWallet = useCasesFacade.needColdWalletInteraction(networks)
|
||||
|
||||
state.update { state ->
|
||||
state.copySealed(
|
||||
hasChanges = currenciesToAdd.isNotEmpty() || currenciesToRemove.isNotEmpty(),
|
||||
needToInteractWithColdWallet = needToInteractWithColdWallet,
|
||||
needToInteractWithColdWallet = isNeedToInteractWithColdWallet,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -324,12 +319,8 @@ internal class ManageTokensModel @Inject constructor(
|
|||
private fun navigateToAddCustomToken() {
|
||||
analyticsEventHandler.send(CustomTokenAnalyticsEvent.ButtonCustomToken(params.source))
|
||||
when (val portfolio = params.mode) {
|
||||
is ManageTokensMode.Wallet ->
|
||||
bottomSheetNavigation
|
||||
.activate(ManageTokensBottomSheetConfig.AddWalletCustomToken(portfolio.userWalletId))
|
||||
is ManageTokensMode.Account ->
|
||||
bottomSheetNavigation
|
||||
.activate(ManageTokensBottomSheetConfig.AddAccountCustomToken(portfolio.accountId))
|
||||
bottomSheetNavigation.activate(portfolio.accountId)
|
||||
ManageTokensMode.None -> Unit
|
||||
}
|
||||
}
|
||||
|
|
@ -347,8 +338,8 @@ internal class ManageTokensModel @Inject constructor(
|
|||
useCasesFacade.saveManagedTokensUseCase(
|
||||
currenciesToAdd = manageTokensListManager.currenciesToAdd.value,
|
||||
currenciesToRemove = manageTokensListManager.currenciesToRemove.value,
|
||||
).getOrElse {
|
||||
Timber.e(it, "Failed to save changes")
|
||||
).getOrElse { throwable ->
|
||||
Timber.e(throwable, "Failed to save changes")
|
||||
return@resource
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,6 @@ import com.tangem.core.ui.event.triggeredEvent
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.redux.OnboardingManageTokensAction
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.features.managetokens.analytics.ManageTokensAnalyticEvent
|
||||
|
|
@ -45,18 +43,13 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
private val messageSender: UiMessageSender,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
accountsFeatureToggles: AccountsFeatureToggles,
|
||||
manageTokensListManagerFactory: ManageTokensListManager.Factory,
|
||||
manageTokensUseCasesFacadeFactory: ManageTokensUseCasesFacade.Factory,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
private val params: OnboardingManageTokensComponent.Params = paramsContainer.require()
|
||||
private val portfolio = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
ManageTokensMode.Account(accountId = AccountId.forMainCryptoPortfolio(params.userWalletId))
|
||||
} else {
|
||||
ManageTokensMode.Wallet(params.userWalletId)
|
||||
}
|
||||
private val portfolio = ManageTokensMode.Account(params.userWalletId)
|
||||
private val useCasesFacade: ManageTokensUseCasesFacade = manageTokensUseCasesFacadeFactory
|
||||
.create(mode = portfolio)
|
||||
private val manageTokensListManager = manageTokensListManagerFactory.create(
|
||||
|
|
@ -223,12 +216,12 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
.flatten()
|
||||
.toSet()
|
||||
.associate { network -> network.backendId to network.derivationPath.value }
|
||||
val showTangemIcon = useCasesFacade.needColdWalletInteraction(network = network)
|
||||
val shouldShowTangemIcon = useCasesFacade.needColdWalletInteraction(network = network)
|
||||
state.update { state ->
|
||||
state.copy(
|
||||
actionButtonConfig = OnboardingManageTokensUM.ActionButtonConfig.Continue(
|
||||
onClick = ::saveChanges,
|
||||
showTangemIcon = showTangemIcon,
|
||||
showTangemIcon = shouldShowTangemIcon,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -267,8 +260,8 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
useCasesFacade.saveManagedTokensUseCase(
|
||||
currenciesToAdd = manageTokensListManager.currenciesToAdd.value,
|
||||
currenciesToRemove = manageTokensListManager.currenciesToRemove.value,
|
||||
).getOrElse {
|
||||
Timber.e(it, "Failed to save changes")
|
||||
).getOrElse { throwable ->
|
||||
Timber.e(throwable, "Failed to save changes")
|
||||
return@resource
|
||||
}
|
||||
|
||||
|
|
@ -292,8 +285,8 @@ internal class OnboardingManageTokensModel @Inject constructor(
|
|||
useCasesFacade.saveManagedTokensUseCase(
|
||||
currenciesToAdd = manageTokensListManager.currenciesToAdd.value,
|
||||
currenciesToRemove = manageTokensListManager.currenciesToRemove.value,
|
||||
).getOrElse {
|
||||
Timber.e(it, "Failed to save changes")
|
||||
).getOrElse { throwable ->
|
||||
Timber.e(throwable, "Failed to save changes")
|
||||
return@resource
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ private fun Preview_AddCustomTokenBottomSheet(
|
|||
}
|
||||
|
||||
private class AddCustomTokenComponentPreviewProvider : PreviewParameterProvider<AddCustomTokenComponent> {
|
||||
private val mode: AddCustomTokenMode get() = AddCustomTokenMode.Wallet(UserWalletId(stringValue = "321"))
|
||||
private val mode: AddCustomTokenMode get() = AddCustomTokenMode(UserWalletId(stringValue = "321"))
|
||||
override val values: Sequence<AddCustomTokenComponent>
|
||||
get() = sequenceOf(
|
||||
PreviewAddCustomTokenComponent(),
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ private class CustomTokenNetworkSelectorComponentPreviewProvider :
|
|||
PreviewParameterProvider<CustomTokenSelectorComponent> {
|
||||
|
||||
private val derivationPath = Network.DerivationPath.Card("m/44'/0'/0'/0/0")
|
||||
private val mode: AddCustomTokenMode get() = AddCustomTokenMode.Wallet(UserWalletId(stringValue = "321"))
|
||||
private val mode: AddCustomTokenMode get() = AddCustomTokenMode(UserWalletId(stringValue = "321"))
|
||||
|
||||
override val values: Sequence<CustomTokenSelectorComponent>
|
||||
get() = sequenceOf(
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ private class PreviewManageTokensComponentProvider : PreviewParameterProvider<Ma
|
|||
showTangemIcon = true,
|
||||
params = ManageTokensComponent.Params(
|
||||
source = ManageTokensSource.ONBOARDING,
|
||||
mode = ManageTokensMode.Wallet(UserWalletId("0x")),
|
||||
mode = ManageTokensMode.Account(UserWalletId("0x")),
|
||||
),
|
||||
),
|
||||
PreviewManageTokensComponent(
|
||||
|
|
@ -459,7 +459,7 @@ private class PreviewManageTokensComponentProvider : PreviewParameterProvider<Ma
|
|||
showTangemIcon = false,
|
||||
params = ManageTokensComponent.Params(
|
||||
source = ManageTokensSource.ONBOARDING,
|
||||
mode = ManageTokensMode.Wallet(UserWalletId("0x")),
|
||||
mode = ManageTokensMode.Account(UserWalletId("0x")),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,34 +7,27 @@ import arrow.core.raise.ensureNotNull
|
|||
import arrow.core.right
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchainsdk.utils.fromNetworkId
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.producer.SingleAccountListProducer
|
||||
import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.managetokens.CheckIsCurrencyNotAddedUseCase
|
||||
import com.tangem.domain.models.account.Account
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.account.DerivationIndex
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.wallets.usecase.DerivePublicKeysUseCase
|
||||
import com.tangem.lib.crypto.derivation.AccountNodeRecognizer
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import timber.log.Timber
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
||||
@Assisted private val userWalletId: UserWalletId,
|
||||
private val derivePublicKeysUseCase: DerivePublicKeysUseCase,
|
||||
private val checkIsCurrencyNotAddedUseCase: CheckIsCurrencyNotAddedUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
) {
|
||||
|
||||
suspend fun addCryptoCurrenciesUseCase(currency: CryptoCurrency): Either<Throwable, Unit> {
|
||||
|
|
@ -45,35 +38,18 @@ internal class CustomTokenFormUseCasesFacade @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun derivePublicKeysUseCase(currencies: List<CryptoCurrency>): Either<Throwable, Unit> {
|
||||
return if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
Unit.right()
|
||||
} else {
|
||||
derivePublicKeysUseCase.invoke(userWalletId = userWalletId, currencies = currencies)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun checkIsCurrencyNotAddedUseCase(
|
||||
networkId: Network.ID,
|
||||
derivationPath: Network.DerivationPath,
|
||||
contractAddress: String?,
|
||||
): Either<Throwable, Boolean> = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
contractAddress = contractAddress,
|
||||
)
|
||||
.fold(ifEmpty = { true }, ifSome = { false })
|
||||
.right()
|
||||
} else {
|
||||
checkIsCurrencyNotAddedUseCase.invoke(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
contractAddress = contractAddress,
|
||||
)
|
||||
}
|
||||
): Either<Throwable, Boolean> = getAccountCurrencyStatusUseCase.invokeSync(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
derivationPath = derivationPath,
|
||||
contractAddress = contractAddress,
|
||||
)
|
||||
.fold(ifEmpty = { true }, ifSome = { false })
|
||||
.right()
|
||||
|
||||
private suspend fun Raise<Throwable>.getAccountId(currency: CryptoCurrency): AccountId {
|
||||
val accountList = singleAccountListSupplier.getSyncOrNull(
|
||||
|
|
|
|||
|
|
@ -89,12 +89,9 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
* @param isCollapsed set initial display state of networks. !!! WARNING !!! Use `false` flag with cation
|
||||
*/
|
||||
suspend fun launchPagination(isCollapsed: Boolean) = coroutineScope {
|
||||
val loadUserTokensFromRemote = when (mode) {
|
||||
is ManageTokensMode.Wallet,
|
||||
is ManageTokensMode.Account,
|
||||
-> source == ManageTokensSource.ONBOARDING
|
||||
ManageTokensMode.None,
|
||||
-> false
|
||||
val shouldLoadTokensFromRemote = when (mode) {
|
||||
is ManageTokensMode.Account -> source == ManageTokensSource.ONBOARDING
|
||||
ManageTokensMode.None -> false
|
||||
}
|
||||
val batchFlow = useCasesFacade.getManagedTokensUseCase(
|
||||
context = ManageTokensListBatchingContext(
|
||||
|
|
@ -102,7 +99,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
coroutineScope = this,
|
||||
),
|
||||
// only for onboarding case, change carefully and check repository implementation
|
||||
loadUserTokensFromRemote = loadUserTokensFromRemote,
|
||||
loadUserTokensFromRemote = shouldLoadTokensFromRemote,
|
||||
)
|
||||
|
||||
batchFlow.state
|
||||
|
|
@ -185,9 +182,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
}
|
||||
|
||||
val canEditItems = when (state.mode) {
|
||||
is ManageTokensMode.Account,
|
||||
is ManageTokensMode.Wallet,
|
||||
-> true
|
||||
is ManageTokensMode.Account -> true
|
||||
ManageTokensMode.None -> false
|
||||
}
|
||||
state.copy(
|
||||
|
|
@ -210,7 +205,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
override fun addCurrency(batchKey: Int, currency: ManagedCryptoCurrency.Token, network: Network) {
|
||||
changedCurrenciesManager.addCurrency(currency, network)
|
||||
|
||||
sendSelectCurrencyAction(batchKey, currency.id, network, isSelected = true)
|
||||
sendSelectCurrencyAction(batchKey = batchKey, currencyId = currency.id, network = network, isSelected = true)
|
||||
|
||||
sendSelectCurrencyAnalyticsEvent(currency, isSelected = true)
|
||||
}
|
||||
|
|
@ -218,7 +213,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
override fun removeCurrency(batchKey: Int, currency: ManagedCryptoCurrency.Token, network: Network) {
|
||||
changedCurrenciesManager.removeCurrency(currency, network)
|
||||
|
||||
sendSelectCurrencyAction(batchKey, currency.id, network, isSelected = false)
|
||||
sendSelectCurrencyAction(batchKey = batchKey, currencyId = currency.id, network = network, isSelected = false)
|
||||
|
||||
sendSelectCurrencyAnalyticsEvent(currency, isSelected = false)
|
||||
}
|
||||
|
|
@ -270,9 +265,9 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
network = network,
|
||||
tempAddedTokens = changedCurrenciesManager.currenciesToAdd.value,
|
||||
tempRemovedTokens = changedCurrenciesManager.currenciesToRemove.value,
|
||||
).getOrElse {
|
||||
).getOrElse { throwable ->
|
||||
Timber.e(
|
||||
it,
|
||||
throwable,
|
||||
"""
|
||||
Failed to check linked tokens
|
||||
|- Mode: $mode
|
||||
|
|
@ -281,7 +276,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
)
|
||||
|
||||
val message = SnackbarMessage(
|
||||
message = it.localizedMessage
|
||||
message = throwable.localizedMessage
|
||||
?.let(::stringReference)
|
||||
?: resourceReference(R.string.common_error),
|
||||
)
|
||||
|
|
@ -296,9 +291,9 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
): CurrencyUnsupportedState? {
|
||||
return useCasesFacade.checkCurrencyUnsupportedUseCase(
|
||||
sourceNetwork = sourceNetwork,
|
||||
).getOrElse {
|
||||
).getOrElse { throwable ->
|
||||
Timber.e(
|
||||
it,
|
||||
throwable,
|
||||
"""
|
||||
Failed to check currency unsupported state
|
||||
|- Mode: $mode
|
||||
|
|
@ -307,7 +302,7 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
)
|
||||
|
||||
val message = SnackbarMessage(
|
||||
message = it.localizedMessage
|
||||
message = throwable.localizedMessage
|
||||
?.let(::stringReference)
|
||||
?: resourceReference(R.string.common_error),
|
||||
)
|
||||
|
|
@ -334,7 +329,12 @@ internal class ManageTokensListManager @AssistedInject constructor(
|
|||
toRemove = currenciesToRemove.value,
|
||||
),
|
||||
onSelectCurrencyNetwork = { networkId, isSelected ->
|
||||
selectNetwork(currencyBatch.key, currency, networkId, isSelected)
|
||||
selectNetwork(
|
||||
batchKey = currencyBatch.key,
|
||||
currency = currency,
|
||||
source = networkId,
|
||||
isSelected = isSelected,
|
||||
)
|
||||
},
|
||||
onLongTap = ::copyContractAddress,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@ package com.tangem.features.managetokens.utils.list
|
|||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.producer.SingleAccountProducer
|
||||
import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase
|
||||
import com.tangem.domain.account.supplier.SingleAccountSupplier
|
||||
import com.tangem.domain.managetokens.CheckCurrencyUnsupportedUseCase
|
||||
import com.tangem.domain.managetokens.CheckHasLinkedTokensUseCase
|
||||
import com.tangem.domain.managetokens.GetDistinctManagedCurrenciesUseCase
|
||||
import com.tangem.domain.managetokens.GetManagedTokensUseCase
|
||||
import com.tangem.domain.managetokens.model.CurrencyUnsupportedState
|
||||
|
|
@ -29,12 +27,10 @@ import dagger.assisted.AssistedInject
|
|||
internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
||||
val getManagedTokensUseCase: GetManagedTokensUseCase,
|
||||
val getDistinctManagedTokensUseCase: GetDistinctManagedCurrenciesUseCase,
|
||||
private val checkHasLinkedTokensUseCase: CheckHasLinkedTokensUseCase,
|
||||
private val checkCurrencyUnsupportedUseCase: CheckCurrencyUnsupportedUseCase,
|
||||
private val coldWalletAndHasMissedDerivationsUseCase: ColdWalletAndHasMissedDerivationsUseCase,
|
||||
private val manageCryptoCurrenciesUseCase: ManageCryptoCurrenciesUseCase,
|
||||
private val customTokensRepository: CustomTokensRepository,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val singleAccountSupplier: SingleAccountSupplier,
|
||||
@Assisted private val mode: ManageTokensMode,
|
||||
) {
|
||||
|
|
@ -45,17 +41,10 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
fun manageTokensListConfig(searchText: String?): ManageTokensListConfig {
|
||||
return when (mode) {
|
||||
is ManageTokensMode.Account -> {
|
||||
ManageTokensListConfig.Account(accountId = mode.accountId, searchText = searchText)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> {
|
||||
ManageTokensListConfig.Wallet(userWalletId = mode.userWalletId, searchText = searchText)
|
||||
ManageTokensListConfig(accountId = mode.accountId, searchText = searchText)
|
||||
}
|
||||
ManageTokensMode.None -> {
|
||||
if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
ManageTokensListConfig.Account(accountId = null, searchText = searchText)
|
||||
} else {
|
||||
ManageTokensListConfig.Wallet(userWalletId = null, searchText = searchText)
|
||||
}
|
||||
ManageTokensListConfig(accountId = null, searchText = searchText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -70,7 +59,6 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
|
||||
manageCryptoCurrenciesUseCase(accountId = mode.accountId, remove = currency)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> error("Unsupported")
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
}
|
||||
|
|
@ -90,18 +78,12 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
) as? Account.CryptoPortfolio
|
||||
?: return IllegalStateException("Account not found").left()
|
||||
|
||||
(account.cryptoCurrencies + added - removed).any {
|
||||
it is CryptoCurrency.Token && it.network.backendId == network.backendId &&
|
||||
it.network.derivationPath == network.derivationPath
|
||||
(account.cryptoCurrencies + added - removed).any { currency ->
|
||||
currency is CryptoCurrency.Token && currency.network.backendId == network.backendId &&
|
||||
currency.network.derivationPath == network.derivationPath
|
||||
}
|
||||
.right()
|
||||
}
|
||||
is ManageTokensMode.Wallet -> checkHasLinkedTokensUseCase.invoke(
|
||||
userWalletId = mode.userWalletId,
|
||||
network = network,
|
||||
tempAddedTokens = tempAddedTokens,
|
||||
tempRemovedTokens = tempRemovedTokens,
|
||||
)
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
}
|
||||
|
|
@ -114,10 +96,6 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
userWalletId = mode.accountId.userWalletId,
|
||||
sourceNetwork = sourceNetwork,
|
||||
)
|
||||
is ManageTokensMode.Wallet -> checkCurrencyUnsupportedUseCase.invoke(
|
||||
userWalletId = mode.userWalletId,
|
||||
sourceNetwork = sourceNetwork,
|
||||
)
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
}
|
||||
|
|
@ -127,10 +105,6 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
userWalletId = mode.accountId.userWalletId,
|
||||
networksWithDerivationPath = network,
|
||||
)
|
||||
is ManageTokensMode.Wallet -> coldWalletAndHasMissedDerivationsUseCase.invoke(
|
||||
userWalletId = mode.userWalletId,
|
||||
networksWithDerivationPath = network,
|
||||
)
|
||||
ManageTokensMode.None -> false
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +119,6 @@ internal class ManageTokensUseCasesFacade @AssistedInject constructor(
|
|||
remove = currenciesToRemove.mapToCryptoCurrencies(userWalletId = mode.accountId.userWalletId),
|
||||
)
|
||||
}
|
||||
is ManageTokensMode.Wallet -> error("Unsupported")
|
||||
ManageTokensMode.None -> nonePortfolioError.left()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ internal class ManageTokensWarningDelegate @AssistedInject constructor(
|
|||
) {
|
||||
val isNonePortfolio = when (mode) {
|
||||
ManageTokensMode.None -> true
|
||||
is ManageTokensMode.Account,
|
||||
is ManageTokensMode.Wallet,
|
||||
-> false
|
||||
is ManageTokensMode.Account -> false
|
||||
}
|
||||
val hasLinkedTokens = if (isNonePortfolio || !isCoin) {
|
||||
false
|
||||
|
|
|
|||
|
|
@ -24,12 +24,10 @@ import com.tangem.core.ui.message.DialogMessage
|
|||
import com.tangem.core.ui.message.EventMessageAction
|
||||
import com.tangem.core.ui.message.SnackbarMessage
|
||||
import com.tangem.core.ui.message.bottomSheetMessage
|
||||
import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles
|
||||
import com.tangem.domain.account.supplier.SingleAccountListSupplier
|
||||
import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase
|
||||
import com.tangem.domain.card.common.util.cardTypesResolver
|
||||
import com.tangem.domain.demo.IsDemoCardUseCase
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
|
@ -87,7 +85,6 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
private val permissionsRepository: PermissionRepository,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
private val unlockHotWalletContextualUseCase: UnlockHotWalletContextualUseCase,
|
||||
private val accountsFeatureToggles: AccountsFeatureToggles,
|
||||
private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase,
|
||||
private val singleAccountListSupplier: SingleAccountListSupplier,
|
||||
private val accountListSortingSaver: AccountListSortingSaver,
|
||||
|
|
@ -159,8 +156,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
accountList = accountList,
|
||||
),
|
||||
accountReorderUM = AccountReorderUM(
|
||||
isDragEnabled = accountsFeatureToggles.isFeatureEnabled &&
|
||||
accountList.count { it is WalletSettingsAccountsUM.Account } > 1,
|
||||
isDragEnabled = accountList.count { it is WalletSettingsAccountsUM.Account } > 1,
|
||||
onMove = ::onAccountReorder,
|
||||
onDragStopped = ::onAccountDragStopped,
|
||||
),
|
||||
|
|
@ -237,13 +233,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
router.push(
|
||||
AppRoute.ManageTokens(
|
||||
source = Source.SETTINGS,
|
||||
portfolioId = if (accountsFeatureToggles.isFeatureEnabled) {
|
||||
PortfolioId(
|
||||
accountId = AccountId.forMainCryptoPortfolio(userWalletId = userWallet.walletId),
|
||||
)
|
||||
} else {
|
||||
PortfolioId(userWalletId = userWallet.walletId)
|
||||
},
|
||||
accountId = AccountId.forMainCryptoPortfolio(userWalletId = userWallet.walletId),
|
||||
),
|
||||
)
|
||||
},
|
||||
|
|
@ -378,7 +368,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
if (!state.value.isWalletBackedUp) {
|
||||
showMakeBackupAtFirstAlertBS()
|
||||
} else {
|
||||
unlockWalletIfNeedAndProceed { authorizationRequired ->
|
||||
unlockWalletIfNeedAndProceed { _ ->
|
||||
router.push(
|
||||
route = AppRoute.UpdateAccessCode(
|
||||
userWalletId = params.userWalletId,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import com.tangem.common.routing.AppRoute
|
|||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.domain.models.PortfolioId
|
||||
import com.tangem.domain.models.TokenReceiveConfig
|
||||
import com.tangem.domain.models.account.AccountId
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
|
|
@ -55,7 +54,7 @@ internal class DefaultWalletRouter @Inject constructor(
|
|||
override fun openManageTokensScreen(accountId: AccountId) {
|
||||
val route = AppRoute.ManageTokens(
|
||||
source = AppRoute.ManageTokens.Source.ACCOUNT,
|
||||
portfolioId = PortfolioId(accountId),
|
||||
accountId = accountId,
|
||||
)
|
||||
router.push(route)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue