Updated on 2026-08-14

This commit is contained in:
Tangem 2026-04-14 13:57:57 +03:00
commit f3dfb262c2
527 changed files with 12898 additions and 3301 deletions

View file

@ -0,0 +1 @@
/build

View file

@ -0,0 +1,27 @@
plugins {
alias(deps.plugins.android.library)
alias(deps.plugins.kotlin.android)
alias(deps.plugins.kotlin.serialization)
id("configuration")
}
android {
namespace = "com.tangem.features.commonfeatures.api"
}
dependencies {
/** Api */ // todo swap delete after move portfolio selector
implementation(projects.features.account.api)
/* Project - Domain */
implementation(projects.domain.models)
implementation(projects.domain.markets)
/* Project - Core */
implementation(projects.core.decompose)
implementation(projects.core.ui)
/* Compose */
implementation(deps.compose.runtime)
implementation(deps.kotlin.immutable.collections)
}

View file

@ -0,0 +1,22 @@
package com.tangem.features.commonfeatures.api.addtoportfolio
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.models.currency.CryptoCurrency
interface AddToPortfolioComponent : ComposableBottomSheetComponent {
data class Params(
val addToPortfolioManager: AddToPortfolioManager,
val callback: Callback,
val shouldSkipTokenActionsScreen: Boolean = false,
)
interface Callback {
fun onDismiss()
// todo swap add new onSuccess with full data of added token
fun onSuccess(addedToken: CryptoCurrency)
}
interface Factory : ComponentFactory<Params, AddToPortfolioComponent>
}

View file

@ -0,0 +1,44 @@
package com.tangem.features.commonfeatures.api.addtoportfolio
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.markets.TokenMarketParams
import com.tangem.features.account.PortfolioFetcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable
interface AddToPortfolioManager {
// todo swap make updatable
val token: TokenMarketParams
val analyticsParams: AnalyticsParams?
val portfolioFetcher: PortfolioFetcher
val state: StateFlow<State>
val allAvailableNetworks: Flow<List<TokenMarketInfo.Network>>
fun setTokenNetworks(networks: List<TokenMarketInfo.Network>)
sealed interface State {
data object Init : State
data class AvailableToAdd(
val availableToAddData: AvailableToAddData,
) : State
data object NothingToAdd : State
}
@Serializable
data class AnalyticsParams(
val source: String,
)
interface Factory {
fun create(
scope: CoroutineScope,
token: TokenMarketParams,
analyticsParams: AnalyticsParams?,
): AddToPortfolioManager
}
}

View file

@ -0,0 +1,38 @@
package com.tangem.features.commonfeatures.api.addtoportfolio
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWalletId
import kotlinx.serialization.Serializable
interface AddToPortfolioPreselectedDataComponent : ComposableBottomSheetComponent {
/**
* @param tokenToAdd token and preselected network (no network selector).
* @param callback callbacks for add-to-portfolio flow.
*/
data class Params(
val tokenToAdd: TokenToAdd,
val callback: Callback,
val analyticsParams: AnalyticsParams,
)
data class AnalyticsParams(val source: String)
interface Callback {
fun onDismiss()
fun onSuccess(addedToken: CryptoCurrency, walletId: UserWalletId)
}
@Serializable
data class TokenToAdd(
val network: TokenMarketInfo.Network,
val id: CryptoCurrency.RawID,
val name: String,
val symbol: String,
)
interface Factory : ComponentFactory<Params, AddToPortfolioPreselectedDataComponent>
}

View file

@ -0,0 +1,61 @@
package com.tangem.features.commonfeatures.api.addtoportfolio
import com.tangem.domain.markets.TokenMarketInfo
import com.tangem.domain.models.account.AccountId
import com.tangem.domain.models.account.AccountStatus
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.models.wallet.UserWalletId
import kotlinx.serialization.Serializable
data class AvailableToAddData(
val availableToAddWallets: Map<UserWalletId, AvailableToAddWallet>,
) {
val isAvailableToAdd: Boolean = availableToAddWallets.values.any { item -> item.isAvailableToAdd }
val isSinglePortfolio: Boolean
get() = availableToAddWallets.size == 1 && availableToAddWallets.values.first().accounts.size == 1
}
data class AvailableToAddWallet(
val userWallet: UserWallet,
val accounts: List<AccountStatus>,
val availableNetworks: Set<TokenMarketInfo.Network>,
val availableToAddAccounts: Map<AccountId, AvailableToAddAccount>,
) {
val isAvailableToAdd: Boolean = availableToAddAccounts.values.any { item -> item.isAvailableToAdd }
}
@Serializable
data class AvailableToAddAccount(
val account: AccountStatus.CryptoPortfolio,
val availableNetworks: Set<TokenMarketInfo.Network>,
val addedNetworks: Set<Network>,
) {
val isSingleNetwork: Boolean
get() = availableNetworks.size == 1
val availableToAddNetworks: Set<TokenMarketInfo.Network> = availableNetworks
.filter { available -> addedNetworks.none { added -> added.rawId == available.networkId } }
.toSet()
val isAvailableToAdd: Boolean = availableToAddNetworks.isNotEmpty()
val addedMarketNetworks: Set<TokenMarketInfo.Network> = availableNetworks
.filter { available -> addedNetworks.any { added -> added.rawId == available.networkId } }
.toSet()
}
@Serializable
data class SelectedPortfolio(
val userWallet: UserWallet,
val account: AvailableToAddAccount,
val isAccountMode: Boolean,
val isAvailableMorePortfolio: Boolean,
)
data class SelectedNetwork(
val selectedNetwork: TokenMarketInfo.Network,
val cryptoCurrency: CryptoCurrency,
val isAvailableMoreNetwork: Boolean,
)