Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-01 16:19:01 +05:00
parent bcc6331bb8
commit 816d8532de
5 changed files with 49 additions and 34 deletions

View file

@ -10,19 +10,21 @@ import com.tangem.domain.express.ExpressRepository
import com.tangem.domain.express.models.ExpressProvider
import com.tangem.domain.express.models.ExpressProviderType
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.filterIf
import timber.log.Timber
internal class DefaultExpressRepository(
private val tangemExpressApi: TangemExpressApi,
private val appPreferencesStore: AppPreferencesStore,
private val dispatchers: CoroutineDispatcherProvider,
) : ExpressRepository {
override suspend fun getProviders(
userWallet: UserWallet,
filterProviderTypes: List<ExpressProviderType>,
): List<ExpressProvider> {
return safeApiCall(
): List<ExpressProvider> = with(dispatchers.io) {
safeApiCall(
call = {
tangemExpressApi.getProviders(
userWalletId = userWallet.walletId.stringValue,

View file

@ -10,6 +10,7 @@ import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.domain.express.ExpressErrorResolver
import com.tangem.domain.express.ExpressRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -34,10 +35,12 @@ internal object ExpressDataModule {
fun provideExpressRepository(
tangemExpressApi: TangemExpressApi,
appPreferencesStore: AppPreferencesStore,
dispatchers: CoroutineDispatcherProvider,
): ExpressRepository {
return DefaultExpressRepository(
tangemExpressApi = tangemExpressApi,
appPreferencesStore = appPreferencesStore,
dispatchers = dispatchers,
)
}
}

View file

@ -7,10 +7,7 @@ import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.*
/**
* Default implementation of [SingleQuoteStatusProducer]
@ -28,7 +25,7 @@ internal class DefaultSingleQuoteStatusProducer @AssistedInject constructor(
override fun produce(): Flow<QuoteStatus> {
return quotesStatusesStore.get()
.mapNotNull { quotes -> quotes.firstOrNull { it.rawCurrencyId == params.rawCurrencyId } }
.mapNotNull { quotes -> quotes.firstOrNull { it.rawCurrencyId == params.rawCurrencyId } ?: fallback }
.distinctUntilChanged()
.flowOn(dispatchers.default)
}

View file

@ -24,6 +24,7 @@ import com.tangem.domain.express.models.ExpressRateType
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.NetworkStatus
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.quotes.single.SingleQuoteStatusFetcher
import com.tangem.domain.quotes.single.SingleQuoteStatusProducer
@ -65,7 +66,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
initialCurrency: CryptoCurrency,
cryptoCurrencyStatusList: List<CryptoCurrencyStatus>,
filterProviderTypes: List<ExpressProviderType>,
): List<SwapPairModel> = withContext(coroutineDispatcher.io) {
): List<SwapPairModel> = withContext(coroutineDispatcher.default) {
val cryptoCurrencyList = cryptoCurrencyStatusList.map { it.currency }
val allPairs = getPairsInternal(
@ -113,7 +114,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
initialCurrency: CryptoCurrency,
cryptoCurrencyList: List<CryptoCurrency>,
filterProviderTypes: List<ExpressProviderType>,
): List<SwapPairModel> = withContext(coroutineDispatcher.io) {
): List<SwapPairModel> = withContext(coroutineDispatcher.default) {
val allPairs = getPairsInternal(
userWallet = userWallet,
initialCurrency = initialCurrency,
@ -330,25 +331,27 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
userWallet: UserWallet,
from: List<CryptoCurrency>,
to: List<CryptoCurrency>,
) = safeApiCall(
call = {
tangemExpressApi.getPairs(
userWalletId = userWallet.walletId.stringValue,
refCode = ExpressUtils.getRefCode(
userWallet = userWallet,
appPreferencesStore = appPreferencesStore,
),
body = PairsRequestBody(
from = tokenInfoConverter.convertList(from),
to = tokenInfoConverter.convertList(to),
),
).getOrThrow()
},
onError = {
Timber.w(it, "Unable to get pairs")
throw it
},
)
) = withContext(coroutineDispatcher.io) {
safeApiCall(
call = {
tangemExpressApi.getPairs(
userWalletId = userWallet.walletId.stringValue,
refCode = ExpressUtils.getRefCode(
userWallet = userWallet,
appPreferencesStore = appPreferencesStore,
),
body = PairsRequestBody(
from = tokenInfoConverter.convertList(from),
to = tokenInfoConverter.convertList(to),
),
).getOrThrow()
},
onError = {
Timber.w(it, "Unable to get pairs")
throw it
},
)
}
/**
* Send with swap specific currency status creation
@ -360,9 +363,9 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
val quote = singleQuoteStatusSupplier.getSyncOrNull(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
)?.right()
)
if (quote == null) {
if (quote == null || quote.value is QuoteStatus.Empty) {
singleQuoteStatusFetcher.invoke(
params = SingleQuoteStatusFetcher.Params(
rawCurrencyId = rawCurrencyId,
@ -373,7 +376,7 @@ internal class DefaultSwapRepositoryV2 @Inject constructor(
return currencyStatusProxyCreator.createCurrencyStatus(
currency = cryptoCurrency,
maybeQuoteStatus = quote ?: singleQuoteStatusSupplier.getSyncOrNull(
maybeQuoteStatus = quote?.right() ?: singleQuoteStatusSupplier.getSyncOrNull(
params = SingleQuoteStatusProducer.Params(rawCurrencyId = rawCurrencyId),
).right(),
maybeNetworkStatus = NetworkStatus(

View file

@ -24,12 +24,13 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastForEach
import androidx.compose.ui.util.fastForEachIndexed
import com.tangem.core.ui.components.SpacerWMax
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.message.*
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
import com.tangem.core.ui.decorations.roundedShapeItemDecoration
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -94,13 +95,22 @@ internal fun SwapChooseTokenNetworkContent(state: SwapChooseTokenNetworkContentU
@Composable
private fun SwapChooseTokenNetworkContentList(swapNetworks: ImmutableList<SwapChooseNetworkUM>) {
Column {
swapNetworks.fastForEach { network ->
Column(
modifier = Modifier
.padding(top = 8.dp)
.padding(16.dp),
) {
swapNetworks.fastForEachIndexed { index, network ->
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(6.dp),
modifier = Modifier
.fillMaxWidth()
.roundedShapeItemDecoration(
currentIndex = index,
lastIndex = swapNetworks.lastIndex,
addDefaultPadding = false,
)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),