Updated on 2026-08-14

This commit is contained in:
Tangem 2025-08-21 12:43:59 +03:00
commit fe2cfac54d
1140 changed files with 23493 additions and 8579 deletions

View file

@ -25,12 +25,12 @@ import com.tangem.datasource.api.express.models.response.TxDetails
import com.tangem.datasource.crypto.DataSignatureVerifier
import com.tangem.datasource.exchangeservice.swap.ExpressUtils
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.feature.swap.converters.*
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.feature.swap.domain.models.ExpressDataError
@ -51,7 +51,7 @@ internal class DefaultSwapRepository(
private val tangemExpressApi: TangemExpressApi,
private val coroutineDispatcher: CoroutineDispatcherProvider,
private val walletManagersFacade: WalletManagersFacade,
private val userWalletsListManager: UserWalletsListManager,
private val userWalletsStore: UserWalletsStore,
private val errorsDataConverter: ErrorsDataConverter,
private val dataSignatureVerifier: DataSignatureVerifier,
private val appPreferencesStore: AppPreferencesStore,
@ -411,7 +411,7 @@ internal class DefaultSwapRepository(
cryptoCurrencyFactory.createCoin(
blockchain = blockchain,
extraDerivationPath = null,
userWallet = requireNotNull(userWalletsListManager.selectedUserWalletSync),
userWallet = requireNotNull(userWalletsStore.selectedUserWalletOrNull),
),
)
}

View file

@ -92,21 +92,37 @@ internal class DefaultSwapTransactionRepository(
key = PreferencesKeys.SWAP_TRANSACTIONS_STATUSES_KEY,
),
) { savedTransactions, txStatuses ->
val currencyTxs = savedTransactions?.filter {
it.userWalletId == userWallet.walletId.stringValue &&
(
it.toCryptoCurrencyId == cryptoCurrencyId.value ||
it.fromCryptoCurrencyId == cryptoCurrencyId.value
)
val currencyToTxs = savedTransactions?.filter {
val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
val toCurrency = it.toCryptoCurrencyId == cryptoCurrencyId.value
isUserWallet && toCurrency
}
currencyTxs?.mapNotNull {
val currencyFromTxs = savedTransactions?.filter {
val isUserWallet = it.userWalletId == userWallet.walletId.stringValue
val fromCurrency = it.fromCryptoCurrencyId == cryptoCurrencyId.value
isUserWallet && fromCurrency
}
val toTxs = currencyToTxs?.mapNotNull {
converter.convertBack(
value = it,
userWallet = userWallet,
txStatuses = txStatuses,
onFilter = { it.swapTxTypeDTO == SwapTxTypeDTO.Swap },
)
}.orEmpty()
val fromTxs = currencyFromTxs?.mapNotNull {
converter.convertBack(
value = it,
userWallet = userWallet,
txStatuses = txStatuses,
)
}
}.orEmpty()
fromTxs + toTxs
}
.flowOn(dispatchers.default)
}

View file

@ -34,6 +34,7 @@ internal class SavedSwapTransactionListConverter(
value: SavedSwapTransactionListModelInner,
userWallet: UserWallet,
txStatuses: Map<String, ExchangeStatusModel>,
onFilter: (SavedSwapTransactionModel) -> Boolean = { true },
): SavedSwapTransactionListModel? {
val fromToken = value.fromTokensResponse
val toToken = value.toTokensResponse
@ -50,17 +51,19 @@ internal class SavedSwapTransactionListConverter(
) ?: return null
return SavedSwapTransactionListModel(
transactions = value.transactions.map { tx ->
val status = txStatuses[tx.txId]
val refundCurrency = status?.refundTokensResponse?.let { id ->
responseCryptoCurrenciesFactory.createCurrency(
responseToken = id,
userWallet = userWallet,
)
}
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
tx.copy(status = statusWithRefundCurrency)
},
transactions = value.transactions
.filter(onFilter)
.map { tx ->
val status = txStatuses[tx.txId]
val refundCurrency = status?.refundTokensResponse?.let { id ->
responseCryptoCurrenciesFactory.createCurrency(
responseToken = id,
userWallet = userWallet,
)
}
val statusWithRefundCurrency = status?.copy(refundCurrency = refundCurrency)
tx.copy(status = statusWithRefundCurrency)
},
userWalletId = value.userWalletId,
fromCryptoCurrencyId = value.fromCryptoCurrencyId,
toCryptoCurrencyId = value.toCryptoCurrencyId,

View file

@ -8,9 +8,9 @@ import com.tangem.datasource.api.express.models.response.ExpressErrorResponse
import com.tangem.datasource.crypto.DataSignatureVerifier
import com.tangem.datasource.di.NetworkMoshi
import com.tangem.datasource.local.preferences.AppPreferencesStore
import com.tangem.datasource.local.userwallet.UserWalletsStore
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.feature.swap.DefaultSwapRepository
import com.tangem.feature.swap.DefaultSwapTransactionRepository
import com.tangem.feature.swap.converters.ErrorsDataConverter
@ -34,7 +34,7 @@ internal class SwapDataModule {
coroutineDispatcher: CoroutineDispatcherProvider,
dataSignature: DataSignatureVerifier,
walletManagerFacade: WalletManagersFacade,
userWalletsListManager: UserWalletsListManager,
userWalletsStore: UserWalletsStore,
errorsDataConverter: ErrorsDataConverter,
@NetworkMoshi moshi: Moshi,
excludedBlockchains: ExcludedBlockchains,
@ -45,7 +45,7 @@ internal class SwapDataModule {
tangemExpressApi = tangemExpressApi,
coroutineDispatcher = coroutineDispatcher,
walletManagersFacade = walletManagerFacade,
userWalletsListManager = userWalletsListManager,
userWalletsStore = userWalletsStore,
errorsDataConverter = errorsDataConverter,
dataSignatureVerifier = dataSignature,
moshi = moshi,

View file

@ -50,4 +50,16 @@ data class SavedSwapTransactionModel(
val provider: SwapProvider,
@Json(name = "status")
val status: ExchangeStatusModel? = null,
)
@Json(name = "swapTxType")
val swapTxTypeDTO: SwapTxTypeDTO? = SwapTxTypeDTO.Swap,
)
// TODO refactor to use separate models to store
@JsonClass(generateAdapter = false)
enum class SwapTxTypeDTO {
@Json(name = "Swap")
Swap,
@Json(name = "SendWithSwap")
SendWithSwap,
}

View file

@ -2,7 +2,7 @@ package com.tangem.feature.swap.domain.models.domain
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import java.math.BigDecimal
/**

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.domain.models.ui
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.feature.swap.domain.models.ExpressDataError
import com.tangem.feature.swap.domain.models.SwapAmount

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.domain
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress
import com.tangem.feature.swap.domain.models.ui.getGroupWithReverse

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.domain
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress

View file

@ -1,7 +1,7 @@
package com.tangem.feature.swap.domain
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.domain.IncludeFeeInAmount

View file

@ -19,6 +19,7 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.demo.IsDemoCardUseCase
import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.quote.QuoteStatus
import com.tangem.domain.models.wallet.UserWallet
@ -26,7 +27,6 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.quotes.QuotesRepository
import com.tangem.domain.quotes.multi.MultiQuoteStatusFetcher
import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.FeePaidCurrency
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.domain.tokens.repository.CurrenciesRepository

View file

@ -61,7 +61,6 @@ dependencies {
/** Compose */
implementation(deps.arrow.core)
implementation(deps.compose.foundation)
implementation(deps.compose.material)
implementation(deps.compose.material3)
implementation(deps.compose.ui.tooling)
implementation(deps.compose.coil)

View file

@ -3,11 +3,11 @@ package com.tangem.feature.swap.converters
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.domain.CryptoCurrencySwapInfo
import com.tangem.feature.swap.models.CurrenciesGroupWithFromCurrency
import com.tangem.feature.swap.models.SwapSelectTokenStateHolder
@ -111,10 +111,11 @@ class TokensDataConverter(
}
private fun formatFiatAmount(cryptoCurrencyStatus: CryptoCurrencyStatus, appCurrency: AppCurrency): String {
return BigDecimalFormatter.formatFiatAmount(
fiatAmount = cryptoCurrencyStatus.value.fiatAmount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
)
return cryptoCurrencyStatus.value.fiatAmount.format {
fiat(
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
)
}
}
}

View file

@ -29,7 +29,11 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase
import com.tangem.domain.feedback.models.BlockchainErrorInfo
import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.models.network.Network
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.promo.GetStoryContentUseCase
import com.tangem.domain.promo.ShouldShowStoriesUseCase
import com.tangem.domain.promo.models.StoryContentIds
@ -40,11 +44,7 @@ import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.models.wallet.requireColdWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.feature.swap.analytics.StoriesEvents
import com.tangem.feature.swap.analytics.SwapEvents
@ -1351,8 +1351,6 @@ internal class SwapModel @Inject constructor(
val transaction = dataState.swapDataModel?.transaction
val fromCurrencyStatus = dataState.fromCryptoCurrency ?: initialFromStatus
val network = fromCurrencyStatus.currency.network
val cardInfo = getCardInfoUseCase(userWallet.requireColdWallet().scanResponse) // TODO [REDACTED_TASK_KEY]
.getOrElse { error("CardInfo must be not null") }
saveBlockchainErrorUseCase(
error = BlockchainErrorInfo(
@ -1366,6 +1364,13 @@ internal class SwapModel @Inject constructor(
),
)
if (userWallet is UserWallet.Hot) {
return@launch // TODO [REDACTED_TASK_KEY] [Hot Wallet] Email feedback flow
}
val cardInfo = getCardInfoUseCase(userWallet.requireColdWallet().scanResponse)
.getOrElse { error("CardInfo must be not null") }
val email = FeedbackEmailType.SwapProblem(
cardInfo = cardInfo,
providerName = dataState.selectedProvider?.name.orEmpty(),

View file

@ -11,7 +11,7 @@ import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.ExpressDataError
import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.domain.IncludeFeeInAmount

View file

@ -1,6 +1,6 @@
package com.tangem.feature.swap.model
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.domain.SwapDataModel
import com.tangem.feature.swap.domain.models.domain.SwapProvider
import com.tangem.feature.swap.domain.models.ui.RequestApproveStateData

View file

@ -10,7 +10,7 @@ import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.event.StateEvent
import com.tangem.core.ui.event.consumedEvent
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.feature.swap.domain.models.ui.PriceImpact
import com.tangem.feature.swap.models.states.FeeItemState
import com.tangem.feature.swap.models.states.ProviderState

View file

@ -8,17 +8,19 @@ import androidx.compose.foundation.text.ClickableText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.components.rows.SelectorRowItem
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SelectNetworkFeeBottomSheetTestTags
import com.tangem.feature.swap.domain.models.ui.FeeType
import com.tangem.feature.swap.models.states.ChooseFeeBottomSheetConfig
import com.tangem.feature.swap.models.states.FeeItemState
@ -89,7 +91,8 @@ private fun FooterBlock(readMore: TextReference, readMoreUrl: String, onReadMore
.padding(
vertical = TangemTheme.dimens.spacing8,
horizontal = TangemTheme.dimens.spacing16,
),
)
.testTag(SelectNetworkFeeBottomSheetTestTags.READ_MORE_TEXT),
style = TangemTheme.typography.caption2.copy(textAlign = TextAlign.Start),
onClick = click,
)
@ -107,7 +110,7 @@ private fun FeeItemsBlock(content: ChooseFeeBottomSheetConfig) {
when (feeItem.feeType) {
FeeType.NORMAL -> {
SelectorRowItem(
titleRes = R.string.common_fee_selector_option_market,
title = resourceReference(R.string.common_fee_selector_option_market),
iconRes = R.drawable.ic_bird_24,
preDot = TextReference.Str(preDotText),
postDot = TextReference.Str(postDot),
@ -119,7 +122,7 @@ private fun FeeItemsBlock(content: ChooseFeeBottomSheetConfig) {
}
FeeType.PRIORITY -> {
SelectorRowItem(
titleRes = R.string.common_fee_selector_option_fast,
title = resourceReference(R.string.common_fee_selector_option_fast),
iconRes = R.drawable.ic_hare_24,
preDot = TextReference.Str(preDotText),
postDot = TextReference.Str(postDot),

View file

@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@ -27,6 +28,7 @@ import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SwapTokenScreenTestTags
import com.tangem.core.ui.utils.GRAY_SCALE_ALPHA
import com.tangem.core.ui.utils.GrayscaleColorFilter
import com.tangem.feature.swap.models.states.PercentDifference
@ -117,7 +119,9 @@ private fun ProviderContentState(
)
Column(
modifier = Modifier.padding(start = TangemTheme.dimens.spacing12),
modifier = Modifier
.padding(start = TangemTheme.dimens.spacing12)
.testTag(SwapTokenScreenTestTags.PROVIDERS_BLOCK),
) {
Row {
if (state.namePrefix == ProviderState.PrefixType.PROVIDED_BY) {

View file

@ -13,13 +13,13 @@ import com.tangem.core.ui.event.triggeredEvent
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.format.bigdecimal.anyDecimals
import com.tangem.core.ui.format.bigdecimal.crypto
import com.tangem.core.ui.format.bigdecimal.fiat
import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.domain.promo.models.StoryContent
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.feature.swap.converters.SwapTransactionErrorStateConverter
import com.tangem.feature.swap.converters.TokensDataConverter
import com.tangem.feature.swap.domain.models.ExpressDataError
@ -1273,7 +1273,12 @@ internal class StateBuilder(
private fun getFormattedFiatAmount(amount: BigDecimal?): String {
val appCurrency = appCurrencyProvider()
return BigDecimalFormatter.formatFiatAmount(amount, appCurrency.code, appCurrency.symbol)
return amount.format {
fiat(
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
)
}
}
private fun SwapAmount.getFormattedCryptoAmount(token: CryptoCurrency): String {

View file

@ -19,6 +19,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
@ -36,6 +37,7 @@ import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.*
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SwapTokenScreenTestTags
import com.tangem.feature.swap.domain.models.ui.FeeType
import com.tangem.feature.swap.domain.models.ui.PriceImpact
import com.tangem.feature.swap.models.*
@ -275,7 +277,8 @@ private fun SwapButton(state: SwapStateHolder, modifier: Modifier = Modifier) {
onClick = state.onChangeCardsClicked,
indication = ripple(),
interactionSource = remember { MutableInteractionSource() },
),
)
.testTag(SwapTokenScreenTestTags.SWAP_BUTTON),
) {
when (state.changeCardsButtonState) {
ChangeCardsButtonState.UPDATE_IN_PROGRESS -> {

View file

@ -23,6 +23,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
@ -39,6 +40,7 @@ import com.tangem.core.ui.extensions.resolveReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.SwapTokenScreenTestTags
import com.tangem.core.ui.utils.ImageBackgroundContrastChecker
import com.tangem.feature.swap.domain.models.ui.PriceImpact
import com.tangem.feature.swap.models.TransactionCardType
@ -181,7 +183,8 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
top = TangemTheme.dimens.spacing14,
start = TangemTheme.dimens.spacing12,
end = TangemTheme.dimens.spacing12,
),
)
.testTag(SwapTokenScreenTestTags.SWAP_BLOCK_HEADER),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
@ -206,7 +209,8 @@ private fun Header(type: TransactionCardType, balance: String, modifier: Modifie
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.body2,
modifier = Modifier
.align(Alignment.CenterVertically),
.align(Alignment.CenterVertically)
.testTag(SwapTokenScreenTestTags.BALANCE),
)
}
} else {
@ -254,7 +258,7 @@ private fun Content(
color = TangemTheme.colors.text.primary1,
style = TangemTheme.typography.h2,
fontSizeRange = FontSizeRange(min = 16.sp, max = TangemTheme.typography.h2.fontSize),
modifier = sumTextModifier,
modifier = sumTextModifier.testTag(SwapTokenScreenTestTags.RECEIVE_TEXT_FIELD),
)
} else {
RectangleShimmer(
@ -269,7 +273,7 @@ private fun Content(
val focusRequester = remember { FocusRequester() }
AutoSizeTextField(
modifier = sumTextModifier,
modifier = sumTextModifier.testTag(SwapTokenScreenTestTags.SWAP_TEXT_FIELD),
focusRequester = focusRequester,
textFieldValue = textFieldValue ?: TextFieldValue(),
onAmountChange = { type.onAmountChanged(it) },
@ -344,7 +348,8 @@ private fun Content(
modifier = Modifier
.padding(vertical = TangemTheme.dimens.spacing4)
.width(TangemTheme.dimens.size40)
.height(TangemTheme.dimens.size12),
.height(TangemTheme.dimens.size12)
.testTag(SwapTokenScreenTestTags.RECEIVE_AMOUNT_SHIMMER),
radius = TangemTheme.dimens.radius3,
)
}
@ -365,7 +370,8 @@ fun Token(
.padding(
end = TangemTheme.dimens.spacing12,
bottom = TangemTheme.dimens.spacing12,
),
)
.testTag(SwapTokenScreenTestTags.TOKEN),
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.End,
) {
@ -382,7 +388,9 @@ fun Token(
maxLines = 1,
style = TangemTheme.typography.subtitle2,
textAlign = TextAlign.Center,
modifier = Modifier.defaultMinSize(minWidth = TangemTheme.dimens.size80),
modifier = Modifier
.defaultMinSize(minWidth = TangemTheme.dimens.size80)
.testTag(SwapTokenScreenTestTags.TOKEN_NAME),
)
}
}
@ -403,7 +411,8 @@ private fun TokenIcon(
Box(
modifier = Modifier
.padding(end = TangemTheme.dimens.spacing16)
.size(TangemTheme.dimens.size42),
.size(TangemTheme.dimens.size42)
.testTag(SwapTokenScreenTestTags.TOKEN_ICON),
) {
val tokenImageModifier = Modifier
.align(Alignment.BottomStart)