Updated on 2026-08-14
This commit is contained in:
commit
0470e1f010
1144 changed files with 48463 additions and 11166 deletions
|
|
@ -12,8 +12,9 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
/** Project - API */
|
||||
implementation(projects.features.account.api)
|
||||
implementation(projects.features.commonFeatures.api)
|
||||
implementation(projects.features.onramp.api)
|
||||
implementation(projects.features.swap.api)
|
||||
implementation(projects.features.swap.domain)
|
||||
|
|
@ -81,5 +82,4 @@ dependencies {
|
|||
/** Other */
|
||||
implementation(deps.decompose.ext.compose)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
implementation(deps.reKotlin)
|
||||
}
|
||||
|
|
@ -2,10 +2,11 @@ package com.tangem.features.onramp.deeplink
|
|||
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import com.tangem.utils.logging.TangemLogger
|
||||
|
||||
internal class DefaultSwapDeepLinkHandler @AssistedInject constructor(
|
||||
router: AppRouter,
|
||||
|
|
@ -19,7 +20,12 @@ internal class DefaultSwapDeepLinkHandler @AssistedInject constructor(
|
|||
TangemLogger.e("Error on getting user wallet: $it")
|
||||
},
|
||||
ifRight = { userWallet ->
|
||||
router.push(AppRoute.SwapCrypto(userWallet.walletId))
|
||||
router.push(
|
||||
AppRoute.Swap(
|
||||
userWalletId = userWallet.walletId,
|
||||
screenSource = AnalyticsParam.ScreensSources.Main.value,
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.features.account.PortfolioSelectorComponent
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorComponent
|
||||
import com.tangem.features.onramp.hottokens.model.HotCryptoModel
|
||||
import com.tangem.features.onramp.hottokens.portfolio.OnrampAddToPortfolioComponent
|
||||
import com.tangem.features.onramp.hottokens.portfolio.OnrampAddTokenComponent
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.features.onramp.hottokens.converter
|
||||
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeType
|
||||
import com.tangem.core.ui.components.marketprice.utils.PriceChangeConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ import com.tangem.domain.models.currency.CryptoCurrency
|
|||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.onramp.model.HotCryptoCurrency
|
||||
import com.tangem.features.account.PortfolioFetcher
|
||||
import com.tangem.features.account.PortfolioSelectorController
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioFetcher
|
||||
import com.tangem.features.commonfeatures.api.portfolioselector.PortfolioSelectorController
|
||||
import com.tangem.features.onramp.hottokens.HotCryptoComponent
|
||||
import com.tangem.features.onramp.hottokens.converter.HotTokenItemStateConverter
|
||||
import com.tangem.features.onramp.hottokens.entity.HotCryptoUM
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ import com.tangem.common.ui.account.toUM
|
|||
import com.tangem.common.ui.addtoken.AddTokenUM
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.iconResId
|
||||
import com.tangem.common.ui.extensions.iconResId
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal class OnrampAddTokenModel @Inject constructor(
|
|||
.distinctUntilChanged()
|
||||
.mapLatest { tokenToAdd: AddHotCryptoData ->
|
||||
addTokenJob.join()
|
||||
val backendId = tokenToAdd.cryptoCurrency.network.backendId
|
||||
val backendId = tokenToAdd.cryptoCurrency.network.rawId
|
||||
val userWalletId = tokenToAdd.account.accountId.userWalletId
|
||||
val isTangemIconVisible = needColdWalletInteraction(
|
||||
walletId = userWalletId,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import com.tangem.core.decompose.context.child
|
|||
import com.tangem.core.decompose.context.childByContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioComponent
|
||||
import com.tangem.features.onramp.component.SwapSelectTokensComponent
|
||||
import com.tangem.features.onramp.swap.availablepairs.AvailableSwapPairsComponent
|
||||
import com.tangem.features.onramp.swap.availablepairs.model.AddToPortfolioRoute
|
||||
|
|
@ -74,9 +74,7 @@ internal class DefaultSwapSelectTokensComponent @AssistedInject constructor(
|
|||
return addToPortfolioComponentFactory.create(
|
||||
context = childByContext(componentContext),
|
||||
params = AddToPortfolioComponent.Params(
|
||||
addToPortfolioManager = selectToTokenListComponent.addToPortfolioManager!!,
|
||||
callback = selectToTokenListComponent.addToPortfolioCallback,
|
||||
shouldSkipTokenActionsScreen = true,
|
||||
addToPortfolioManager = selectToTokenListComponent.addToPortfolioManager,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ import com.tangem.core.ui.components.token.state.TokenItemState
|
|||
import com.tangem.core.ui.decompose.ComposableListContentComponent
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
||||
import com.tangem.features.onramp.swap.availablepairs.model.AddToPortfolioRoute
|
||||
import com.tangem.features.onramp.tokenlist.entity.TokenListUM
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -18,8 +17,7 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
internal interface AvailableSwapPairsComponent : ComposableListContentComponent<TokenListUM> {
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<AddToPortfolioRoute>
|
||||
val addToPortfolioManager: AddToPortfolioManager?
|
||||
val addToPortfolioCallback: AddToPortfolioComponent.Callback
|
||||
val addToPortfolioManager: AddToPortfolioManager
|
||||
|
||||
/** Component factory */
|
||||
interface Factory : ComponentFactory<Params, AvailableSwapPairsComponent>
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ import androidx.compose.ui.Modifier
|
|||
import com.arkivanov.decompose.router.slot.SlotNavigation
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
||||
import com.tangem.features.onramp.swap.availablepairs.model.AddToPortfolioRoute
|
||||
import com.tangem.features.onramp.swap.availablepairs.model.AvailableSwapPairsModel
|
||||
import com.tangem.features.onramp.tokenlist.entity.TokenListUM
|
||||
|
|
@ -26,8 +25,7 @@ internal class DefaultAvailableSwapPairsComponent @AssistedInject constructor(
|
|||
private val model: AvailableSwapPairsModel = getOrCreateModel(params)
|
||||
|
||||
override val bottomSheetNavigation: SlotNavigation<AddToPortfolioRoute> get() = model.bottomSheetNavigation
|
||||
override val addToPortfolioManager: AddToPortfolioManager? get() = model.addToPortfolioManager
|
||||
override val addToPortfolioCallback: AddToPortfolioComponent.Callback get() = model.addToPortfolioCallback
|
||||
override val addToPortfolioManager: AddToPortfolioManager get() = model.addToPortfolioManager
|
||||
|
||||
override val uiState: StateFlow<TokenListUM>
|
||||
get() = model.state
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
|||
import com.tangem.feature.swap.domain.GetAvailablePairsUseCase
|
||||
import com.tangem.feature.swap.domain.models.domain.LeastTokenInfo
|
||||
import com.tangem.feature.swap.domain.models.domain.SwapPairLeast
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioComponent
|
||||
import com.tangem.features.feed.components.market.details.portfolio.add.AddToPortfolioManager
|
||||
import com.tangem.features.commonfeatures.api.addtoportfolio.AddToPortfolioManager
|
||||
import com.tangem.features.onramp.impl.R
|
||||
import com.tangem.features.onramp.swap.availablepairs.AvailableSwapPairsComponent
|
||||
import com.tangem.features.onramp.swap.availablepairs.entity.transformers.SetErrorWarningTransformer
|
||||
|
|
@ -62,13 +61,10 @@ import com.tangem.features.onramp.utils.ClearSearchBarTransformer
|
|||
import com.tangem.features.onramp.utils.UpdateSearchBarActiveStateTransformer
|
||||
import com.tangem.features.onramp.utils.UpdateSearchBarCallbacksTransformer
|
||||
import com.tangem.features.onramp.utils.UpdateSearchQueryTransformer
|
||||
import com.tangem.features.swap.SwapFeatureToggles
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.runSuspendCatching
|
||||
import com.tangem.utils.coroutines.saveIn
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -93,7 +89,6 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
private val addToPortfolioManagerFactory: AddToPortfolioManager.Factory,
|
||||
private val excludedBlockchains: ExcludedBlockchains,
|
||||
private val getAccountCurrencyStatusUseCase: GetAccountCurrencyStatusUseCase,
|
||||
swapFeatureToggles: SwapFeatureToggles,
|
||||
getWalletsUseCase: GetWalletsUseCase,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -104,14 +99,12 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
private val allUserWallets = getWalletsUseCase.invokeSync()
|
||||
|
||||
val bottomSheetNavigation: SlotNavigation<AddToPortfolioRoute> = SlotNavigation()
|
||||
var addToPortfolioManager: AddToPortfolioManager? = null
|
||||
val addToPortfolioCallback: AddToPortfolioComponent.Callback = object : AddToPortfolioComponent.Callback {
|
||||
override fun onDismiss() = bottomSheetNavigation.dismiss()
|
||||
override fun onSuccess(addedToken: CryptoCurrency) {
|
||||
onTokenAddedToPortfolio(addedToken)
|
||||
}
|
||||
}
|
||||
private val addToPortfolioJobHolder = JobHolder()
|
||||
val addToPortfolioManager: AddToPortfolioManager = addToPortfolioManagerFactory
|
||||
.create(
|
||||
scope = modelScope,
|
||||
analyticsParams = AddToPortfolioManager.AnalyticsParams(source = ScreensSources.Swap.value),
|
||||
settings = AddToPortfolioManager.Settings.ChooseToken,
|
||||
)
|
||||
|
||||
private val accountListFlow = getAccountListUseCaseFlow()
|
||||
private val availablePairsByNetworkFlow = MutableStateFlow<Map<LeastTokenInfo, AvailablePairsState>>(emptyMap())
|
||||
|
|
@ -155,10 +148,14 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
subscribeOnSelectedStatusChange()
|
||||
subscribeOnAvailablePairsUpdates()
|
||||
|
||||
if (swapFeatureToggles.isMarketListFeatureEnabled) {
|
||||
subscribeOnMarketsUpdates()
|
||||
subscribeOnVisibleMarketItems()
|
||||
}
|
||||
subscribeOnMarketsUpdates()
|
||||
subscribeOnVisibleMarketItems()
|
||||
addToPortfolioManager.onDismiss.receiveAsFlow()
|
||||
.onEach { bottomSheetNavigation.dismiss() }
|
||||
.launchIn(modelScope)
|
||||
addToPortfolioManager.onSuccessAdded.receiveAsFlow()
|
||||
.onEach { result -> onTokenAddedToPortfolio(result.addedCurrency.currency) }
|
||||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun getAccountListUseCaseFlow(): SharedFlow<List<AccountStatus>> {
|
||||
|
|
@ -251,7 +248,7 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
.associate { accountStatus ->
|
||||
val statuses = accountStatus.tokenList.flattenCurrencies()
|
||||
.filterNot { status ->
|
||||
status.currency.network.backendId == selectedStatus?.currency?.network?.backendId &&
|
||||
status.currency.network.rawId == selectedStatus?.currency?.network?.rawId &&
|
||||
status.currency.id.contractAddress == selectedStatus.currency.id.contractAddress
|
||||
}
|
||||
.filterByQuery(query = query)
|
||||
|
|
@ -458,7 +455,7 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
private fun CryptoCurrencyStatus.toLeastTokenInfo(): LeastTokenInfo {
|
||||
return LeastTokenInfo(
|
||||
contractAddress = (currency as? CryptoCurrency.Token)?.contractAddress ?: "0",
|
||||
network = currency.network.backendId,
|
||||
network = currency.network.rawId,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -593,45 +590,35 @@ internal class AvailableSwapPairsModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun addToPortfolioItem(item: MarketsListItemUM) {
|
||||
modelScope.launch {
|
||||
val tokenMarket = defaultMarketsListManager.getTokenMarketById(item.id)
|
||||
?: searchMarketsListManager.getTokenMarketById(item.id)
|
||||
?: return@launch
|
||||
val tokenMarket = defaultMarketsListManager.getTokenMarketById(item.id)
|
||||
?: searchMarketsListManager.getTokenMarketById(item.id)
|
||||
?: return
|
||||
|
||||
val param = tokenMarket.toSerializableParam()
|
||||
val hasOnlyHotWallets = allUserWallets.all { it is UserWallet.Hot }
|
||||
val param = tokenMarket.toSerializableParam()
|
||||
val hasOnlyHotWallets = allUserWallets.all { it is UserWallet.Hot }
|
||||
|
||||
val networks = tokenMarket.networks?.filter { network ->
|
||||
BlockchainUtils.isSupportedNetworkId(
|
||||
blockchainId = network.networkId,
|
||||
coinId = tokenMarket.id.value,
|
||||
contractAddress = network.contractAddress,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
hotExcludedBlockchains = hotWalletExcludedBlockchains,
|
||||
hasOnlyHotWallets = hasOnlyHotWallets,
|
||||
)
|
||||
}?.map { network ->
|
||||
TokenMarketInfo.Network(
|
||||
networkId = network.networkId,
|
||||
isExchangeable = false,
|
||||
contractAddress = network.contractAddress,
|
||||
decimalCount = network.decimalCount,
|
||||
)
|
||||
}.orEmpty()
|
||||
val networks = tokenMarket.networks?.filter { network ->
|
||||
BlockchainUtils.isSupportedNetworkId(
|
||||
networkId = network.networkId,
|
||||
coinId = tokenMarket.id.value,
|
||||
contractAddress = network.contractAddress,
|
||||
excludedBlockchains = excludedBlockchains,
|
||||
hotExcludedBlockchains = hotWalletExcludedBlockchains,
|
||||
hasOnlyHotWallets = hasOnlyHotWallets,
|
||||
)
|
||||
}?.map { network ->
|
||||
TokenMarketInfo.Network(
|
||||
networkId = network.networkId,
|
||||
isExchangeable = false,
|
||||
contractAddress = network.contractAddress,
|
||||
decimalCount = network.decimalCount,
|
||||
)
|
||||
}.orEmpty()
|
||||
|
||||
addToPortfolioManager = addToPortfolioManagerFactory
|
||||
.create(
|
||||
scope = modelScope,
|
||||
token = param,
|
||||
analyticsParams = AddToPortfolioManager.AnalyticsParams(source = ScreensSources.Swap.value),
|
||||
).apply {
|
||||
setTokenNetworks(networks)
|
||||
}
|
||||
addToPortfolioManager.setTokenNetworks(networks)
|
||||
addToPortfolioManager.setTokenParams(param)
|
||||
|
||||
addToPortfolioManager?.state
|
||||
?.firstOrNull { it is AddToPortfolioManager.State.AvailableToAdd }
|
||||
?.run { bottomSheetNavigation.activate(AddToPortfolioRoute) }
|
||||
}.saveIn(addToPortfolioJobHolder)
|
||||
bottomSheetNavigation.activate(AddToPortfolioRoute)
|
||||
}
|
||||
|
||||
private fun subscribeOnVisibleMarketItems() {
|
||||
|
|
|
|||
|
|
@ -114,8 +114,7 @@ internal class SwapSelectTokensModel @Inject constructor(
|
|||
|
||||
router.push(
|
||||
route = AppRoute.Swap(
|
||||
currencyFrom = requireNotNull(fromCurrencyStatus.value).currency,
|
||||
currencyTo = status.currency,
|
||||
cryptoCurrency = requireNotNull(fromCurrencyStatus.value).currency,
|
||||
userWalletId = params.userWalletId,
|
||||
screenSource = AnalyticsParam.ScreensSources.Main.value,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.common.getTotalCryptoAmount
|
|||
import com.tangem.common.getTotalFiatAmount
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter
|
||||
import com.tangem.common.ui.tokens.TokenItemStateConverter.Companion.isFlickering
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.token.state.TokenItemState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
|
|
|
|||
|
|
@ -309,10 +309,7 @@ internal class OnrampTokenListModel @Inject constructor(
|
|||
).isRight()
|
||||
}
|
||||
OnrampOperation.SWAP -> {
|
||||
val isAvailable = rampStateManager.availableForSwap(
|
||||
userWalletId = params.userWalletId,
|
||||
cryptoCurrency = status.currency,
|
||||
).isAvailable() && !status.currency.isCustom
|
||||
val isAvailable = !status.currency.isCustom
|
||||
|
||||
val supplyStatus = status.value.yieldSupplyStatus
|
||||
val isUnavailableByYieldSupply = supplyStatus?.isAllowedToSpend == false && supplyStatus.isActive
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue