Updated on 2026-08-14
This commit is contained in:
parent
8f639cbc60
commit
c215778788
16 changed files with 230 additions and 88 deletions
|
|
@ -103,6 +103,12 @@ internal object TokensDomainModule {
|
|||
return FetchCurrencyStatusUseCase(currenciesRepository, networksRepository, quotesRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCryptoCurrencyUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrencyUseCase {
|
||||
return GetCryptoCurrencyUseCase(currenciesRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideToggleTokenListGroupingUseCase(
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ import com.tangem.common.flatMap
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsArguments
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
|
||||
|
|
@ -17,6 +20,7 @@ import com.tangem.tap.common.extensions.dispatchErrorNotification
|
|||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.converters.CryptoCurrencyConverter
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
|
|
@ -40,8 +44,7 @@ class MultiWalletMiddleware {
|
|||
is WalletAction.MultiWallet.SelectWallet -> {
|
||||
if (action.currency != null) {
|
||||
val bundle = bundleOf(
|
||||
// TODO: [REDACTED_JIRA]
|
||||
TokenDetailsRouter.SELECTED_CURRENCY_KEY to cryptoCurrencyConverter.convert(action.currency),
|
||||
TokenDetailsRouter.TOKEN_DETAILS_ARGS to createTokenDetailsArgument(action.currency),
|
||||
)
|
||||
store.dispatch(NavigationAction.NavigateTo(screen = AppScreen.WalletDetails, bundle = bundle))
|
||||
}
|
||||
|
|
@ -130,4 +133,21 @@ class MultiWalletMiddleware {
|
|||
store.state.globalState.tapWalletManager.loadData(updatedUserWallet, refresh = true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTokenDetailsArgument(currency: Currency): TokenDetailsArguments {
|
||||
val cryptoCurrency = cryptoCurrencyConverter.convert(currency)
|
||||
return TokenDetailsArguments(
|
||||
currencyId = cryptoCurrency.id,
|
||||
currencyName = cryptoCurrency.name,
|
||||
iconUrl = cryptoCurrency.iconUrl,
|
||||
coinType = when (cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> TokenDetailsArguments.CoinType.Native
|
||||
is CryptoCurrency.Token -> TokenDetailsArguments.CoinType.Token(
|
||||
standardName = cryptoCurrency.network.standardType.name,
|
||||
networkName = cryptoCurrency.network.name,
|
||||
networkIcon = cryptoCurrency.networkIconResId,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,14 @@
|
|||
plugins {
|
||||
alias(deps.plugins.kotlin.jvm)
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("kotlin-parcelize")
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.domain.tokens.model"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.domain.txhistory.models)
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.tokens.model
|
||||
|
||||
import java.io.Serializable
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* Represents a generic cryptocurrency.
|
||||
|
|
@ -13,8 +14,7 @@ import java.io.Serializable
|
|||
* @property iconUrl Optional URL of the cryptocurrency icon. `null` if not found.
|
||||
* @property isCustom Indicates whether the currency is a custom user-added currency or not.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
sealed class CryptoCurrency : Serializable {
|
||||
sealed class CryptoCurrency {
|
||||
|
||||
abstract val id: ID
|
||||
abstract val network: Network
|
||||
|
|
@ -74,29 +74,31 @@ sealed class CryptoCurrency : Serializable {
|
|||
* @property rawCurrencyId Represents not unique currency ID from the blockchain network. `null` if
|
||||
* its ID of the custom token.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
@Parcelize
|
||||
data class ID(
|
||||
private val prefix: Prefix,
|
||||
private val body: Body,
|
||||
private val suffix: Suffix,
|
||||
) : Serializable {
|
||||
) : Parcelable {
|
||||
|
||||
val value: String = buildString {
|
||||
append(prefix.value)
|
||||
append(PREFIX_DELIMITER)
|
||||
append(body.value)
|
||||
append(SUFFIX_DELIMITER)
|
||||
append(suffix.value)
|
||||
}
|
||||
val value: String
|
||||
get() = buildString {
|
||||
append(prefix.value)
|
||||
append(PREFIX_DELIMITER)
|
||||
append(body.value)
|
||||
append(SUFFIX_DELIMITER)
|
||||
append(suffix.value)
|
||||
}
|
||||
|
||||
/** Represents a raw cryptocurrency ID. If it is a custom token, the value will be `null`. */
|
||||
val rawCurrencyId: String? = (suffix as? Suffix.RawID)?.rawId
|
||||
val rawCurrencyId: String? get() = (suffix as? Suffix.RawID)?.rawId
|
||||
|
||||
/** Represents a raw cryptocurrency's network ID. */
|
||||
val rawNetworkId: String = when (body) {
|
||||
is Body.NetworkId -> body.rawId
|
||||
is Body.NetworkIdWithDerivationPath -> body.rawId
|
||||
}
|
||||
val rawNetworkId: String
|
||||
get() = when (body) {
|
||||
is Body.NetworkId -> body.rawId
|
||||
is Body.NetworkIdWithDerivationPath -> body.rawId
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the different types of prefixes that can be associated with a cryptocurrency ID.
|
||||
|
|
@ -116,14 +118,15 @@ sealed class CryptoCurrency : Serializable {
|
|||
*
|
||||
* The body can be either a raw network ID or a raw network ID with a network derivation path.
|
||||
*/
|
||||
sealed class Body : Serializable {
|
||||
@Parcelize
|
||||
sealed class Body : Parcelable {
|
||||
|
||||
/** The value of the body. */
|
||||
abstract val value: String
|
||||
|
||||
/** Represents a raw network ID. */
|
||||
data class NetworkId(val rawId: String) : Body() {
|
||||
override val value: String = rawId
|
||||
override val value: String get() = rawId
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -135,11 +138,12 @@ sealed class CryptoCurrency : Serializable {
|
|||
val rawId: String,
|
||||
val derivationPath: String,
|
||||
) : Body() {
|
||||
override val value: String = buildString {
|
||||
append(rawId)
|
||||
append(DERIVATION_PATH_DELIMITER)
|
||||
append(derivationPath.hashCode())
|
||||
}
|
||||
override val value: String
|
||||
get() = buildString {
|
||||
append(rawId)
|
||||
append(DERIVATION_PATH_DELIMITER)
|
||||
append(derivationPath.hashCode())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,20 +152,20 @@ sealed class CryptoCurrency : Serializable {
|
|||
*
|
||||
* The suffix can either be a raw ID or a contract address.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
sealed class Suffix : Serializable {
|
||||
@Parcelize
|
||||
sealed class Suffix : Parcelable {
|
||||
|
||||
/** The value of the suffix, which could be either a raw ID or a contract address. */
|
||||
abstract val value: String
|
||||
|
||||
/** Represents a raw ID suffix. */
|
||||
data class RawID(val rawId: String) : Suffix() {
|
||||
override val value: String = rawId
|
||||
override val value: String get() = rawId
|
||||
}
|
||||
|
||||
/** Represents a contract address suffix. */
|
||||
data class ContractAddress(val contractAddress: String) : Suffix() {
|
||||
override val value: String = contractAddress
|
||||
override val value: String get() = contractAddress
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.tangem.domain.tokens.model
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Represents a blockchain network, identified by a unique ID, a human-readable name, and its standard type.
|
||||
*
|
||||
|
|
@ -15,14 +13,13 @@ import java.io.Serializable
|
|||
* @property isTestnet Indicates whether the network is a test network or a main network.
|
||||
* @property standardType The type of blockchain standard the network adheres to.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
data class Network(
|
||||
val id: ID,
|
||||
val name: String,
|
||||
val derivationPath: DerivationPath,
|
||||
val isTestnet: Boolean,
|
||||
val standardType: StandardType,
|
||||
) : Serializable {
|
||||
) {
|
||||
|
||||
init {
|
||||
require(name.isNotBlank()) { "Network name must not be blank" }
|
||||
|
|
@ -47,7 +44,7 @@ data class Network(
|
|||
* This class represents such paths in a generic manner, allowing for predefined card-based paths,
|
||||
* custom paths, or even no derivation path at all.
|
||||
*/
|
||||
sealed class DerivationPath : Serializable {
|
||||
sealed class DerivationPath {
|
||||
|
||||
/** The actual derivation path value, if any. */
|
||||
abstract val value: String?
|
||||
|
|
@ -83,8 +80,7 @@ data class Network(
|
|||
*
|
||||
* @property name The human-readable name of the standard type.
|
||||
*/
|
||||
// FIXME: Remove serialization [REDACTED_JIRA]
|
||||
sealed class StandardType : Serializable {
|
||||
sealed class StandardType {
|
||||
abstract val name: String
|
||||
|
||||
/** Represents the ERC20 token standard, common on the Ethereum network. */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.raise.Raise
|
||||
import arrow.core.raise.catch
|
||||
import arrow.core.raise.either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
class GetCryptoCurrencyUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
) {
|
||||
|
||||
/**
|
||||
* Returns specific cryptocurrency for a given user wallet.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @param id The ID of the cryptocurrency.
|
||||
* @return An [Either] representing success (Right) or an error (Left) in fetching the status.
|
||||
*/
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): Either<CurrencyStatusError, CryptoCurrency> {
|
||||
return either { getCurrency(userWalletId, id) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primary cryptocurrency for a given user wallet.
|
||||
*
|
||||
* @param userWalletId The ID of the user's wallet.
|
||||
* @return An [Either] representing success (Right) or an error (Left) in fetching the status.
|
||||
*/
|
||||
suspend operator fun invoke(userWalletId: UserWalletId): Either<CurrencyStatusError, CryptoCurrency> {
|
||||
return either { getPrimaryCurrency(userWalletId) }
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyStatusError>.getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
id: CryptoCurrency.ID,
|
||||
): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getMultiCurrencyWalletCurrency(userWalletId, id) },
|
||||
catch = { raise(CurrencyStatusError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun Raise<CurrencyStatusError>.getPrimaryCurrency(userWalletId: UserWalletId): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) },
|
||||
catch = { raise(CurrencyStatusError.DataError(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("kotlin-parcelize")
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
|
|
@ -9,6 +10,8 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.domain.tokens.models)
|
||||
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package com.tangem.features.tokendetails.navigation
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.annotation.DrawableRes
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@Parcelize
|
||||
data class TokenDetailsArguments(
|
||||
val currencyId: CryptoCurrency.ID,
|
||||
val currencyName: String,
|
||||
val iconUrl: String?,
|
||||
val coinType: CoinType,
|
||||
) : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
sealed class CoinType : Parcelable {
|
||||
object Native : CoinType()
|
||||
|
||||
/**
|
||||
* @param standardName - token standard. Samples: ERC20, BEP20, BEP2, TRC20 and etc.
|
||||
* @param networkName - token's blockchain name. Ethereum, Tron and etc.
|
||||
*/
|
||||
data class Token(
|
||||
val standardName: String,
|
||||
val networkName: String,
|
||||
@DrawableRes val networkIcon: Int,
|
||||
) : CoinType()
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,6 @@ interface TokenDetailsRouter {
|
|||
fun getEntryFragment(): Fragment
|
||||
|
||||
companion object {
|
||||
const val SELECTED_CURRENCY_KEY = "selected_currency"
|
||||
const val TOKEN_DETAILS_ARGS = "token_details_args"
|
||||
}
|
||||
}
|
||||
|
|
@ -39,9 +39,9 @@ internal object TokenDetailsPreviewData {
|
|||
name = "Tether (USDT) with long name test",
|
||||
iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/large/stellar.png",
|
||||
currency = TokenInfoBlockState.Currency.Token(
|
||||
networkName = "ERC20",
|
||||
standardName = "ERC20",
|
||||
networkIcon = R.drawable.img_eth_22,
|
||||
blockchainName = "Ethereum",
|
||||
networkName = "Ethereum",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -49,9 +49,9 @@ internal object TokenDetailsPreviewData {
|
|||
name = "Tether USDT",
|
||||
iconUrl = "https://s3.eu-central-1.amazonaws.com/tangem.api/coins/large/tether.png",
|
||||
currency = TokenInfoBlockState.Currency.Token(
|
||||
networkName = "ERC20",
|
||||
standardName = "ERC20",
|
||||
networkIcon = R.drawable.img_eth_22,
|
||||
blockchainName = "Ethereum",
|
||||
networkName = "Ethereum",
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,19 +4,20 @@ import androidx.annotation.DrawableRes
|
|||
|
||||
internal data class TokenInfoBlockState(
|
||||
val name: String,
|
||||
val iconUrl: String,
|
||||
val iconUrl: String?,
|
||||
val currency: Currency,
|
||||
) {
|
||||
sealed class Currency {
|
||||
object Native : Currency()
|
||||
|
||||
/**
|
||||
* @param networkName - token standard. Samples: ERC20, BEP20, BEP2, TRC20 and etc.
|
||||
* @param blockchainName - token's blockchain name. Ethereum, Tron and etc.
|
||||
* @param standardName - token standard. Samples: ERC20, BEP20, BEP2, TRC20 and etc.
|
||||
* @param networkName - token's network name.
|
||||
* @param networkIcon - token's network icon.
|
||||
*/
|
||||
data class Token(
|
||||
val standardName: String,
|
||||
val networkName: String,
|
||||
val blockchainName: String,
|
||||
@DrawableRes val networkIcon: Int,
|
||||
) : Currency()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory
|
|||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.*
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsActionButton
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsPullToRefreshConfig
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsSkeletonStateConverter.SkeletonModel
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
|
||||
import com.tangem.features.tokendetails.impl.R
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsArguments
|
||||
import com.tangem.utils.converter.Converter
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
|
@ -19,30 +17,28 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
|
||||
internal class TokenDetailsSkeletonStateConverter(
|
||||
private val clickIntents: TokenDetailsClickIntents,
|
||||
) : Converter<SkeletonModel, TokenDetailsState> {
|
||||
) : Converter<TokenDetailsArguments, TokenDetailsState> {
|
||||
|
||||
override fun convert(value: SkeletonModel): TokenDetailsState {
|
||||
override fun convert(value: TokenDetailsArguments): TokenDetailsState {
|
||||
return TokenDetailsState(
|
||||
topAppBarConfig = TokenDetailsTopAppBarConfig(
|
||||
onBackClick = clickIntents::onBackClick,
|
||||
tokenDetailsAppBarMenuConfig = createMenu(),
|
||||
),
|
||||
tokenInfoBlockState = TokenInfoBlockState(
|
||||
name = value.cryptoCurrency.name,
|
||||
iconUrl = requireNotNull(value.cryptoCurrency.iconUrl),
|
||||
currency = when (val currency = value.cryptoCurrency) {
|
||||
is CryptoCurrency.Coin -> TokenInfoBlockState.Currency.Native
|
||||
is CryptoCurrency.Token -> TokenInfoBlockState.Currency.Token(
|
||||
networkName = currency.network.standardType.name,
|
||||
blockchainName = currency.network.name,
|
||||
networkIcon = currency.networkIconResId,
|
||||
name = value.currencyName,
|
||||
iconUrl = value.iconUrl,
|
||||
currency = when (val coinType = value.coinType) {
|
||||
TokenDetailsArguments.CoinType.Native -> TokenInfoBlockState.Currency.Native
|
||||
is TokenDetailsArguments.CoinType.Token -> TokenInfoBlockState.Currency.Token(
|
||||
standardName = coinType.networkName,
|
||||
networkName = coinType.networkName,
|
||||
networkIcon = coinType.networkIcon,
|
||||
)
|
||||
},
|
||||
),
|
||||
tokenBalanceBlockState = TokenDetailsBalanceBlockState.Loading(
|
||||
actionButtons = createButtons(),
|
||||
),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(value.cryptoCurrency.name),
|
||||
tokenBalanceBlockState = TokenDetailsBalanceBlockState.Loading(actionButtons = createButtons()),
|
||||
marketPriceBlockState = MarketPriceBlockState.Loading(value.currencyName),
|
||||
notifications = persistentListOf(),
|
||||
pendingTxs = persistentListOf(),
|
||||
txHistoryState = TxHistoryState.Content(
|
||||
|
|
@ -80,6 +76,4 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
isRefreshing = false,
|
||||
onRefresh = clickIntents::onRefreshSwipe,
|
||||
)
|
||||
|
||||
data class SkeletonModel(val cryptoCurrency: CryptoCurrency)
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.component
|
|||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadedTxHistoryConverter
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsLoadingTxHistoryConverter
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsArguments
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal class TokenDetailsStateFactory(
|
||||
|
|
@ -30,8 +31,8 @@ internal class TokenDetailsStateFactory(
|
|||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val isBalanceHiddenProvider: Provider<Boolean>,
|
||||
private val clickIntents: TokenDetailsClickIntents,
|
||||
symbol: String,
|
||||
decimals: Int,
|
||||
currencySymbolProvider: Provider<String>,
|
||||
currencyDecimalsProvider: Provider<Int>,
|
||||
) {
|
||||
|
||||
private val skeletonStateConverter by lazy {
|
||||
|
|
@ -47,8 +48,8 @@ internal class TokenDetailsStateFactory(
|
|||
currentStateProvider = currentStateProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
isBalanceHiddenProvider = isBalanceHiddenProvider,
|
||||
symbol = symbol,
|
||||
decimals = decimals,
|
||||
symbol = currencySymbolProvider(),
|
||||
decimals = currencyDecimalsProvider(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -67,8 +68,8 @@ internal class TokenDetailsStateFactory(
|
|||
TokenDetailsLoadedTxHistoryConverter(
|
||||
currentStateProvider = currentStateProvider,
|
||||
clickIntents = clickIntents,
|
||||
symbol = symbol,
|
||||
decimals = decimals,
|
||||
symbol = currencySymbolProvider(),
|
||||
decimals = currencyDecimalsProvider(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +79,8 @@ internal class TokenDetailsStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
fun getInitialState(cryptoCurrency: CryptoCurrency): TokenDetailsState {
|
||||
return skeletonStateConverter.convert(
|
||||
TokenDetailsSkeletonStateConverter.SkeletonModel(cryptoCurrency = cryptoCurrency),
|
||||
)
|
||||
fun getInitialState(screenArgument: TokenDetailsArguments): TokenDetailsState {
|
||||
return skeletonStateConverter.convert(value = screenArgument)
|
||||
}
|
||||
|
||||
fun getCurrencyLoadedBalanceState(
|
||||
|
|
|
|||
|
|
@ -95,8 +95,8 @@ private fun extractNetwork(tokenCurrency: TokenInfoBlockState.Currency.Token): E
|
|||
val splitString = stringResource(
|
||||
id = R.string.token_details_token_type_subtitle,
|
||||
formatArgs = arrayOf(
|
||||
tokenCurrency.standardName,
|
||||
tokenCurrency.networkName,
|
||||
tokenCurrency.blockchainName,
|
||||
),
|
||||
).split(SEPARATOR)
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
|||
import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
|
||||
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsArguments
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
|
|
@ -55,13 +56,14 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val isBalanceHiddenUseCase: IsBalanceHiddenUseCase,
|
||||
private val listenToFlipsUseCase: ListenToFlipsUseCase,
|
||||
private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase,
|
||||
private val getCryptoCurrencyUseCase: GetCryptoCurrencyUseCase,
|
||||
private val walletManagersFacade: WalletManagersFacade,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
|
||||
|
||||
private val cryptoCurrency: CryptoCurrency = savedStateHandle[TokenDetailsRouter.SELECTED_CURRENCY_KEY]
|
||||
?: error("no expected parameter CryptoCurrency found")
|
||||
private val screenArgument: TokenDetailsArguments = savedStateHandle[TokenDetailsRouter.TOKEN_DETAILS_ARGS]
|
||||
?: error("This screen can't open without TokenDetailsArgument")
|
||||
|
||||
var router by Delegates.notNull<InnerTokenDetailsRouter>()
|
||||
|
||||
|
|
@ -69,6 +71,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val refreshStateJobHolder = JobHolder()
|
||||
private var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
|
||||
private var wallet by Delegates.notNull<UserWallet>()
|
||||
private var cryptoCurrency by Delegates.notNull<CryptoCurrency>()
|
||||
|
||||
private val selectedAppCurrencyFlow: StateFlow<AppCurrency> = createSelectedAppCurrencyFlow()
|
||||
private var isBalanceHidden = true
|
||||
|
|
@ -78,25 +81,34 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
|
||||
isBalanceHiddenProvider = Provider { isBalanceHidden },
|
||||
clickIntents = this,
|
||||
symbol = cryptoCurrency.symbol,
|
||||
decimals = cryptoCurrency.decimals,
|
||||
currencySymbolProvider = Provider { cryptoCurrency.symbol },
|
||||
currencyDecimalsProvider = Provider { cryptoCurrency.decimals },
|
||||
)
|
||||
|
||||
var uiState: TokenDetailsState by mutableStateOf(stateFactory.getInitialState(cryptoCurrency))
|
||||
var uiState: TokenDetailsState by mutableStateOf(stateFactory.getInitialState(screenArgument))
|
||||
private set
|
||||
|
||||
override fun onCreate(owner: LifecycleOwner) {
|
||||
getWallet()
|
||||
updateContent(selectedWallet = wallet)
|
||||
initRequiredFields()
|
||||
handleBalanceHiding(owner)
|
||||
}
|
||||
|
||||
private fun getWallet() {
|
||||
return getSelectedWalletUseCase()
|
||||
private fun initRequiredFields() {
|
||||
getSelectedWalletUseCase()
|
||||
.fold(
|
||||
ifLeft = { error("Can not get selected wallet $it") },
|
||||
ifRight = { wallet = it },
|
||||
)
|
||||
viewModelScope.launch {
|
||||
getCryptoCurrencyUseCase.invoke(userWalletId = wallet.walletId, id = screenArgument.currencyId)
|
||||
.fold(
|
||||
ifLeft = { error("Can not get cryptoCurrency with given ID: screenArgument.currencyId. $it") },
|
||||
ifRight = {
|
||||
cryptoCurrency = it
|
||||
updateContent(selectedWallet = wallet)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContent(selectedWallet: UserWallet) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import androidx.navigation.navArgument
|
|||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.navigation.ReduxNavController
|
||||
import com.tangem.core.ui.extensions.networkIconResId
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.feature.wallet.presentation.WalletFragment
|
||||
|
|
@ -26,6 +27,7 @@ import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensScree
|
|||
import com.tangem.feature.wallet.presentation.organizetokens.OrganizeTokensViewModel
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletViewModel
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsArguments
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
|
@ -111,8 +113,21 @@ internal class DefaultWalletRouter(private val reduxNavController: ReduxNavContr
|
|||
reduxNavController.navigate(
|
||||
action = NavigationAction.NavigateTo(
|
||||
screen = AppScreen.WalletDetails,
|
||||
// TODO: [REDACTED_JIRA]
|
||||
bundle = bundleOf(TokenDetailsRouter.SELECTED_CURRENCY_KEY to currency),
|
||||
bundle = bundleOf(
|
||||
TokenDetailsRouter.TOKEN_DETAILS_ARGS to TokenDetailsArguments(
|
||||
currencyId = currency.id,
|
||||
currencyName = currency.name,
|
||||
iconUrl = currency.iconUrl,
|
||||
coinType = when (currency) {
|
||||
is CryptoCurrency.Coin -> TokenDetailsArguments.CoinType.Native
|
||||
is CryptoCurrency.Token -> TokenDetailsArguments.CoinType.Token(
|
||||
standardName = currency.network.standardType.name,
|
||||
networkName = currency.network.name,
|
||||
networkIcon = currency.networkIconResId,
|
||||
)
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue