Updated on 2026-08-14
This commit is contained in:
parent
1061426e87
commit
343c3ad9fb
16 changed files with 340 additions and 37 deletions
|
|
@ -117,6 +117,22 @@ internal object TokensDomainModule {
|
|||
return GetCryptoCurrencyActionsUseCase(rampStateManager, marketCryptoCurrencyRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCurrencyStatusByNetworkUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
quotesRepository: QuotesRepository,
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetNetworkCoinStatusUseCase {
|
||||
return GetNetworkCoinStatusUseCase(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
dispatchers = dispatchers,
|
||||
)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCurrenciesUseCase(currenciesRepository: CurrenciesRepository): GetCryptoCurrenciesUseCase {
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ import com.tangem.feature.swap.presentation.SwapFragment
|
|||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.TapError
|
||||
import com.tangem.tap.domain.tokens.getIconUrl
|
||||
import com.tangem.tap.features.demo.DemoHelper
|
||||
import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE
|
||||
|
|
@ -39,7 +41,10 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import com.tangem.feature.swap.domain.models.domain.Currency as SwapCurrency
|
||||
|
||||
@Suppress("LargeClass")
|
||||
class TradeCryptoMiddleware {
|
||||
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
fun handle(state: () -> AppState?, action: TradeCryptoAction) {
|
||||
if (DemoHelper.tryHandle(state, action)) return
|
||||
|
||||
|
|
@ -52,11 +57,10 @@ class TradeCryptoMiddleware {
|
|||
openSwap(currency = store.state.walletState.selectedWalletData?.currency?.toSwapCurrency())
|
||||
}
|
||||
is TradeCryptoAction.New.Buy -> proceedNewBuyAction(state, action)
|
||||
TradeCryptoAction.New.Send -> store.dispatch(WalletAction.Send())
|
||||
is TradeCryptoAction.New.Sell -> proceedNewSellAction(action)
|
||||
is TradeCryptoAction.New.Swap -> {
|
||||
openSwap(currency = action.cryptoCurrency.toSwapCurrency())
|
||||
}
|
||||
is TradeCryptoAction.New.Swap -> openSwap(currency = action.cryptoCurrency.toSwapCurrency())
|
||||
is TradeCryptoAction.New.SendToken -> handleNewSendToken(action = action)
|
||||
is TradeCryptoAction.New.SendCoin -> handleNewSendCoin(action = action)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,4 +305,98 @@ class TradeCryptoMiddleware {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNewSendToken(action: TradeCryptoAction.New.SendToken) {
|
||||
val cryptoStatus = action.tokenStatus
|
||||
val currency = cryptoStatus.currency
|
||||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWallet = action.userWallet,
|
||||
blockchain = blockchain,
|
||||
derivationPath = blockchain.derivationPath(
|
||||
style = action.userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
),
|
||||
)
|
||||
|
||||
if (walletManager == null) {
|
||||
val error = TapError.UnsupportedState(stateError = "WalletManager is null")
|
||||
FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError))
|
||||
store.dispatchErrorNotification(error)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val sendableAmounts = walletManager.wallet.amounts.values.filter { it.type is AmountType.Token }
|
||||
when (currency) {
|
||||
is CryptoCurrency.Coin -> error("Action.tokenStatus.currency is Coin")
|
||||
is CryptoCurrency.Token -> {
|
||||
store.dispatchOnMain(
|
||||
action = PrepareSendScreen(
|
||||
walletManager = walletManager,
|
||||
coinAmount = walletManager.wallet.amounts[AmountType.Coin],
|
||||
coinRate = action.coinFiatRate,
|
||||
tokenAmount = sendableAmounts.first(),
|
||||
tokenRate = cryptoStatus.value.fiatRate,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNewSendCoin(action: TradeCryptoAction.New.SendCoin) {
|
||||
val cryptoStatus = action.coinStatus
|
||||
val currency = cryptoStatus.currency
|
||||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWallet = action.userWallet,
|
||||
blockchain = blockchain,
|
||||
derivationPath = blockchain.derivationPath(
|
||||
style = action.userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
),
|
||||
)
|
||||
|
||||
if (walletManager == null) {
|
||||
val error = TapError.UnsupportedState(stateError = "WalletManager is null")
|
||||
FirebaseCrashlytics.getInstance().recordException(IllegalStateException(error.stateError))
|
||||
store.dispatchErrorNotification(error)
|
||||
return@launch
|
||||
}
|
||||
|
||||
val sendableAmounts = walletManager.wallet.amounts.values.filter { it.type == AmountType.Coin }
|
||||
when (currency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
val amountToSend = sendableAmounts.find { it.currencySymbol == currency.symbol }
|
||||
|
||||
if (amountToSend == null) {
|
||||
val error = TapError.UnsupportedState(stateError = "Amount to send is null")
|
||||
FirebaseCrashlytics.getInstance()
|
||||
.recordException(IllegalStateException(error.stateError))
|
||||
store.dispatchErrorNotification(error)
|
||||
return@launch
|
||||
}
|
||||
|
||||
store.dispatchOnMain(
|
||||
action = PrepareSendScreen(
|
||||
walletManager = walletManager,
|
||||
coinAmount = amountToSend,
|
||||
coinRate = cryptoStatus.value.fiatRate,
|
||||
),
|
||||
)
|
||||
}
|
||||
is CryptoCurrency.Token -> error("Action.tokenStatus.currency is Token")
|
||||
}
|
||||
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Send))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.data.tokens.repository
|
||||
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.data.common.cache.CacheRegistry
|
||||
import com.tangem.data.tokens.utils.*
|
||||
import com.tangem.datasource.api.tangemTech.TangemTechApi
|
||||
|
|
@ -7,10 +8,12 @@ import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
|
|||
import com.tangem.datasource.local.token.UserMarketCoinsStore
|
||||
import com.tangem.datasource.local.token.UserTokensStore
|
||||
import com.tangem.datasource.local.userwallet.UserWalletsStore
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -190,6 +193,27 @@ internal class DefaultCurrenciesRepository(
|
|||
responseCurrenciesFactory.createCurrency(id, response, userWallet.scanResponse.card)
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin {
|
||||
val userWallet = getUserWallet(userWalletId)
|
||||
ensureIsCorrectUserWallet(userWallet = userWallet, isMultiCurrencyWalletExpected = true)
|
||||
|
||||
fetchTokensIfCacheExpired(userWallet = userWallet, refresh = false)
|
||||
|
||||
val storedTokens = requireNotNull(userTokensStore.getSyncOrNull(userWallet.walletId)) {
|
||||
"Unable to find tokens response for user wallet with provided ID: $userWalletId"
|
||||
}
|
||||
|
||||
val storedCoin = storedTokens.tokens.find { it.networkId == Blockchain.fromId(networkId.value).toNetworkId() }
|
||||
?: error("Coin in this network $networkId not found")
|
||||
|
||||
val coin = responseCurrenciesFactory.createCurrency(
|
||||
responseToken = storedCoin,
|
||||
card = userWallet.scanResponse.card,
|
||||
)
|
||||
|
||||
return coin as? CryptoCurrency.Coin ?: error("Unable to create currency")
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return channelFlow {
|
||||
ensureIsCorrectUserWallet(userWalletId, isMultiCurrencyWalletExpected = true)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ internal class ResponseCurrenciesFactory(private val demoConfig: DemoConfig) {
|
|||
return response.tokens.mapNotNull { createCurrency(it, card) }
|
||||
}
|
||||
|
||||
private fun createCurrency(responseToken: UserTokensResponse.Token, card: CardDTO): CryptoCurrency? {
|
||||
fun createCurrency(responseToken: UserTokensResponse.Token, card: CardDTO): CryptoCurrency? {
|
||||
var blockchain = Blockchain.fromNetworkId(responseToken.networkId)
|
||||
if (blockchain == null || blockchain == Blockchain.Unknown) {
|
||||
Timber.e("Unable to find a blockchain with the network ID: ${responseToken.networkId}")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.CurrencyStatusError
|
||||
import com.tangem.domain.tokens.error.mapper.mapToCurrencyError
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.tokens.operations.CurrenciesStatusesOperations
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.tokens.repository.NetworksRepository
|
||||
import com.tangem.domain.tokens.repository.QuotesRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
||||
class GetNetworkCoinStatusUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val quotesRepository: QuotesRepository,
|
||||
private val networksRepository: NetworksRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
return flow {
|
||||
emitAll(
|
||||
flow = getCurrency(
|
||||
userWalletId = userWalletId,
|
||||
networkId = networkId,
|
||||
),
|
||||
)
|
||||
}
|
||||
.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
private suspend fun getCurrency(
|
||||
userWalletId: UserWalletId,
|
||||
networkId: Network.ID,
|
||||
): Flow<Either<CurrencyStatusError, CryptoCurrencyStatus>> {
|
||||
val operations = CurrenciesStatusesOperations(
|
||||
currenciesRepository = currenciesRepository,
|
||||
quotesRepository = quotesRepository,
|
||||
networksRepository = networksRepository,
|
||||
userWalletId = userWalletId,
|
||||
)
|
||||
|
||||
return operations.getNetworkCoinFlow(networkId).map { maybeCurrency ->
|
||||
maybeCurrency.mapLeft(CurrenciesStatusesOperations.Error::mapToCurrencyError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
|||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import org.rekotlin.Action
|
||||
import java.math.BigDecimal
|
||||
|
||||
sealed class TradeCryptoAction : Action {
|
||||
|
||||
|
|
@ -36,7 +37,13 @@ sealed class TradeCryptoAction : Action {
|
|||
val appCurrencyCode: String,
|
||||
) : New()
|
||||
|
||||
object Send : New()
|
||||
data class SendToken(
|
||||
val userWallet: UserWallet,
|
||||
val tokenStatus: CryptoCurrencyStatus,
|
||||
val coinFiatRate: BigDecimal?,
|
||||
) : New()
|
||||
|
||||
data class SendCoin(val userWallet: UserWallet, val coinStatus: CryptoCurrencyStatus) : New()
|
||||
|
||||
data class Swap(val cryptoCurrency: CryptoCurrency) : New()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,15 @@ internal class CurrenciesStatusesOperations(
|
|||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getNetworkCoinFlow(networkId: Network.ID): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getNetworkCoin(networkId) },
|
||||
recover = { return flowOf(it.left()) },
|
||||
)
|
||||
|
||||
return getCurrencyStatusFlow(currency)
|
||||
}
|
||||
|
||||
suspend fun getPrimaryCurrencyStatusFlow(): Flow<Either<Error, CryptoCurrencyStatus>> {
|
||||
val currency = recover(
|
||||
block = { getPrimaryCurrency() },
|
||||
|
|
@ -177,6 +186,12 @@ internal class CurrenciesStatusesOperations(
|
|||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getNetworkCoin(networkId: Network.ID): CryptoCurrency {
|
||||
return Either.catch { currenciesRepository.getNetworkCoin(userWalletId, networkId) }
|
||||
.mapLeft { Error.DataError(it) }
|
||||
.bind()
|
||||
}
|
||||
|
||||
private suspend fun Raise<Error>.getPrimaryCurrency(): CryptoCurrency {
|
||||
return catch(
|
||||
block = { currenciesRepository.getSingleCurrencyWalletPrimaryCurrency(userWalletId) },
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
|
@ -103,6 +104,14 @@ interface CurrenciesRepository {
|
|||
*/
|
||||
suspend fun getMultiCurrencyWalletCurrency(userWalletId: UserWalletId, id: CryptoCurrency.ID): CryptoCurrency
|
||||
|
||||
/**
|
||||
* Get the coin for a specific network.
|
||||
*
|
||||
* @param userWalletId The unique identifier of the user wallet.
|
||||
* @param networkId The unique identifier of the network.
|
||||
*/
|
||||
suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin
|
||||
|
||||
/**
|
||||
* Determines whether the tokens within a specific multi-currency user wallet are grouped.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import arrow.core.Either
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.domain.core.error.DataError
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.tokens.models.Network
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
|
@ -74,6 +75,10 @@ internal class MockCurrenciesRepository(
|
|||
return token
|
||||
}
|
||||
|
||||
override suspend fun getNetworkCoin(userWalletId: UserWalletId, networkId: Network.ID): CryptoCurrency.Coin {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Boolean> {
|
||||
return isGrouped.map { it.getOrElse { e -> throw e } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
|||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.tokens.GetCryptoCurrencyActionsUseCase
|
||||
import com.tangem.domain.tokens.RemoveCurrencyUseCase
|
||||
import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase
|
||||
import com.tangem.domain.tokens.GetNetworkCoinStatusUseCase
|
||||
import com.tangem.domain.tokens.RemoveCurrencyUseCase
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
|
|
@ -48,6 +49,7 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
private val getExploreUrlUseCase: GetExploreUrlUseCase,
|
||||
private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCase,
|
||||
private val removeCurrencyUseCase: RemoveCurrencyUseCase,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val reduxStateHolder: ReduxStateHolder,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(), DefaultLifecycleObserver, TokenDetailsClickIntents {
|
||||
|
|
@ -169,7 +171,40 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onSendClick() {
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.New.Send)
|
||||
val cryptoCurrencyStatus = cryptoCurrencyStatus ?: return
|
||||
|
||||
when (cryptoCurrencyStatus.currency) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendCoin(
|
||||
userWallet = wallet,
|
||||
coinStatus = cryptoCurrencyStatus,
|
||||
),
|
||||
)
|
||||
}
|
||||
is CryptoCurrency.Token -> sendToken(status = cryptoCurrencyStatus)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendToken(status: CryptoCurrencyStatus) {
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
getNetworkCoinStatusUseCase(
|
||||
userWalletId = wallet.walletId,
|
||||
networkId = status.currency.network.id,
|
||||
)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
it.onRight { coinStatus ->
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendToken(
|
||||
userWallet = wallet,
|
||||
tokenStatus = status,
|
||||
coinFiatRate = coinStatus.value.fiatRate,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceiveClick() {
|
||||
|
|
|
|||
|
|
@ -1,36 +1,32 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state.factory
|
||||
|
||||
import com.tangem.common.Provider
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.TokenActionButtonConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletState
|
||||
import com.tangem.feature.wallet.presentation.wallet.viewmodels.WalletClickIntents
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
/**
|
||||
* Converter from loaded [TokenItemState.Content] to ImmutableList<[TokenActionButtonConfig]>
|
||||
*
|
||||
* @property currentStateProvider current ui state provider
|
||||
* @property clickIntents screen click intents
|
||||
*
|
||||
*/
|
||||
@Suppress("UnusedPrivateMember")
|
||||
internal class TokenActionsProvider(
|
||||
private val currentStateProvider: Provider<WalletState>,
|
||||
) {
|
||||
internal class TokenActionsProvider(private val clickIntents: WalletClickIntents) {
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
fun provideActions(tokenId: String): ImmutableList<TokenActionButtonConfig> {
|
||||
fun provideActions(cryptoCurrencyStatus: CryptoCurrencyStatus): ImmutableList<TokenActionButtonConfig> {
|
||||
// TODO: [REDACTED_JIRA]
|
||||
return mockTokenActionButtonConfig().toImmutableList()
|
||||
return mockTokenActionButtonConfig(cryptoCurrencyStatus).toImmutableList()
|
||||
}
|
||||
|
||||
private fun mockTokenActionButtonConfig(): List<TokenActionButtonConfig> {
|
||||
private fun mockTokenActionButtonConfig(cryptoCurrencyStatus: CryptoCurrencyStatus): List<TokenActionButtonConfig> {
|
||||
return listOf(
|
||||
TokenActionButtonConfig(
|
||||
text = "Send",
|
||||
iconResId = R.drawable.ic_plus_24,
|
||||
onClick = {},
|
||||
onClick = { clickIntents.onMultiCurrencySendClick(cryptoCurrencyStatus) },
|
||||
),
|
||||
TokenActionButtonConfig(
|
||||
text = "Buy",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ internal class WalletCryptoCurrencyActionsConverter(
|
|||
WalletManageButton.Sell(enabled = action.enabled, onClick = clickIntents::onSellClick)
|
||||
}
|
||||
is TokenActionsState.ActionState.Send -> {
|
||||
WalletManageButton.Send(enabled = action.enabled, onClick = clickIntents::onSendClick)
|
||||
WalletManageButton.Send(
|
||||
enabled = action.enabled,
|
||||
onClick = clickIntents::onSingleCurrencySendClick,
|
||||
)
|
||||
}
|
||||
is TokenActionsState.ActionState.Swap -> null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ internal class WalletStateFactory(
|
|||
private val clickIntents: WalletClickIntents,
|
||||
) {
|
||||
|
||||
private val tokenActionsProvider by lazy { TokenActionsProvider(currentStateProvider = currentStateProvider) }
|
||||
private val tokenActionsProvider by lazy { TokenActionsProvider(clickIntents) }
|
||||
private val skeletonConverter by lazy { WalletSkeletonStateConverter(currentStateProvider, clickIntents) }
|
||||
|
||||
private val tokenListErrorConverter by lazy {
|
||||
|
|
@ -185,12 +185,12 @@ internal class WalletStateFactory(
|
|||
}
|
||||
}
|
||||
|
||||
fun getStateWithTokenActionBottomSheet(tokenId: String): WalletState {
|
||||
fun getStateWithTokenActionBottomSheet(currencyStatus: CryptoCurrencyStatus): WalletState {
|
||||
return when (val state = currentStateProvider() as WalletState.ContentState) {
|
||||
is WalletMultiCurrencyState.Content -> state.copy(
|
||||
tokenActionsBottomSheet = ActionsBottomSheetConfig(
|
||||
isShow = true,
|
||||
actions = tokenActionsProvider.provideActions(tokenId = tokenId),
|
||||
actions = tokenActionsProvider.provideActions(currencyStatus),
|
||||
onDismissRequest = clickIntents::onDismissActionsBottomSheet,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
|
|||
)
|
||||
},
|
||||
onItemClick = { clickIntents.onTokenItemClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(currency) },
|
||||
onItemLongClick = { clickIntents.onTokenItemLongClick(cryptoCurrencyStatus = this) },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.viewmodels
|
||||
|
||||
import com.tangem.core.ui.components.transactions.intents.TxHistoryClickIntents
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
||||
|
|
@ -39,7 +40,7 @@ internal interface WalletClickIntents : TxHistoryClickIntents {
|
|||
|
||||
fun onTokenItemClick(currency: CryptoCurrency)
|
||||
|
||||
fun onTokenItemLongClick(currency: CryptoCurrency)
|
||||
fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus)
|
||||
|
||||
fun onDismissActionsBottomSheet()
|
||||
|
||||
|
|
@ -47,7 +48,9 @@ internal interface WalletClickIntents : TxHistoryClickIntents {
|
|||
|
||||
fun onDeleteClick(userWalletId: UserWalletId)
|
||||
|
||||
fun onSendClick()
|
||||
fun onSingleCurrencySendClick(cryptoCurrencyStatus: CryptoCurrencyStatus? = null)
|
||||
|
||||
fun onMultiCurrencySendClick(cryptoCurrencyStatus: CryptoCurrencyStatus)
|
||||
|
||||
fun onReceiveClick()
|
||||
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
private val fetchTokenListUseCase: FetchTokenListUseCase,
|
||||
private val getPrimaryCurrencyStatusUpdatesUseCase: GetPrimaryCurrencyStatusUpdatesUseCase,
|
||||
private val fetchCurrencyStatusUseCase: FetchCurrencyStatusUseCase,
|
||||
private val getNetworkCoinStatusUseCase: GetNetworkCoinStatusUseCase,
|
||||
private val getCardWasScannedUseCase: GetCardWasScannedUseCase,
|
||||
private val isUserAlreadyRateAppUseCase: IsUserAlreadyRateAppUseCase,
|
||||
private val isDemoCardUseCase: IsDemoCardUseCase,
|
||||
|
|
@ -121,7 +122,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
var uiState: WalletState by uiStateHolder(initialState = stateFactory.getInitialState())
|
||||
|
||||
private var wallets: List<UserWallet> by Delegates.notNull()
|
||||
private var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
|
||||
private var singleWalletCryptoCurrencyStatus: CryptoCurrencyStatus? = null
|
||||
|
||||
private val tokensJobHolder = JobHolder()
|
||||
private val marketPriceJobHolder = JobHolder()
|
||||
|
|
@ -300,7 +301,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
|
||||
override fun onBuyClick() {
|
||||
val state = uiState as? WalletState.ContentState ?: return
|
||||
val status = cryptoCurrencyStatus ?: return
|
||||
val status = singleWalletCryptoCurrencyStatus ?: return
|
||||
val wallet = getWallet(index = state.walletsListConfig.selectedWalletIndex)
|
||||
|
||||
reduxStateHolder.dispatch(
|
||||
|
|
@ -312,8 +313,48 @@ internal class WalletViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun onSendClick() {
|
||||
reduxStateHolder.dispatch(TradeCryptoAction.New.Send)
|
||||
override fun onSingleCurrencySendClick(cryptoCurrencyStatus: CryptoCurrencyStatus?) {
|
||||
val state = uiState as? WalletState.ContentState ?: return
|
||||
|
||||
val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex)
|
||||
val coinStatus = if (userWallet.isMultiCurrency) cryptoCurrencyStatus else singleWalletCryptoCurrencyStatus
|
||||
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendCoin(
|
||||
userWallet = userWallet,
|
||||
coinStatus = coinStatus ?: return,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onMultiCurrencySendClick(cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
if (cryptoCurrencyStatus.currency is CryptoCurrency.Coin) {
|
||||
onSingleCurrencySendClick(cryptoCurrencyStatus = cryptoCurrencyStatus)
|
||||
return
|
||||
}
|
||||
|
||||
val state = uiState as? WalletState.ContentState ?: return
|
||||
|
||||
viewModelScope.launch(dispatchers.io) {
|
||||
val userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex)
|
||||
|
||||
getNetworkCoinStatusUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
networkId = cryptoCurrencyStatus.currency.network.id,
|
||||
)
|
||||
.take(count = 1)
|
||||
.collectLatest {
|
||||
it.onRight { coinStatus ->
|
||||
reduxStateHolder.dispatch(
|
||||
action = TradeCryptoAction.New.SendToken(
|
||||
userWallet = getWallet(index = state.walletsListConfig.selectedWalletIndex),
|
||||
tokenStatus = cryptoCurrencyStatus,
|
||||
coinFiatRate = coinStatus.value.fiatRate,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onReceiveClick() {
|
||||
|
|
@ -321,7 +362,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onSellClick() {
|
||||
val status = cryptoCurrencyStatus ?: return
|
||||
val status = singleWalletCryptoCurrencyStatus ?: return
|
||||
|
||||
reduxStateHolder.dispatch(
|
||||
TradeCryptoAction.New.Sell(
|
||||
|
|
@ -384,10 +425,8 @@ internal class WalletViewModel @Inject constructor(
|
|||
router.openTokenDetails(currency = currency)
|
||||
}
|
||||
|
||||
override fun onTokenItemLongClick(currency: CryptoCurrency) {
|
||||
uiState = stateFactory.getStateWithTokenActionBottomSheet(
|
||||
tokenId = currency.id.value,
|
||||
)
|
||||
override fun onTokenItemLongClick(cryptoCurrencyStatus: CryptoCurrencyStatus) {
|
||||
uiState = stateFactory.getStateWithTokenActionBottomSheet(cryptoCurrencyStatus)
|
||||
}
|
||||
|
||||
override fun onRenameClick(userWalletId: UserWalletId, name: String) {
|
||||
|
|
@ -504,7 +543,7 @@ internal class WalletViewModel @Inject constructor(
|
|||
uiState = stateFactory.getSingleCurrencyLoadedBalanceState(maybeCryptoCurrencyStatus)
|
||||
|
||||
maybeCryptoCurrencyStatus.onRight { status ->
|
||||
cryptoCurrencyStatus = status
|
||||
singleWalletCryptoCurrencyStatus = status
|
||||
updateButtons(userWalletId = userWalletId, currency = status.currency)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue