Updated on 2026-08-14

This commit is contained in:
Tangem 2024-03-27 12:43:32 +01:00
parent 9ad7cd63ee
commit a6ab6a6eaf
13 changed files with 131 additions and 75 deletions

View file

@ -183,6 +183,9 @@
<string name="express_choose_providers_subtitle">Tangem предоставляет доступ к обмену через сторонних поставщиков в соответствии с их правилами</string>
<string name="express_choose_providers_title">Выберите провайдера</string>
<string name="express_error_code">Произошла ошибка. Код: %s</string>
<string name="express_error_provider_unavailable">К сожалению обмен указанной пары через выбранного провайдера на данный момент не возможен. Попробуйте совершить обмен позже. (Код:\u00A0%s)</string>
<string name="express_error_swap_pair_unavailable">Выбранный провайдер не доступен для обмена. Попробуйте позже. (Код:\u00A0%s)</string>
<string name="express_error_swap_unavailable">В данный момент обмен не возможен. Попробуйте позже. (Код:\u00A0%s)</string>
<string name="express_estimated_amount">Курс обмена</string>
<string name="express_exchange_by">Обмен через %s</string>
<string name="express_exchange_notification_failed_text">Чтобы вернуть ваши деньги, посетите сайт провайдера</string>
@ -273,10 +276,11 @@
<string name="onboarding_access_code_feature_1_title">Защита</string>
<string name="onboarding_access_code_feature_2_description">Позже вы сможете установить индивидуальный код доступа для каждой карты</string>
<string name="onboarding_access_code_feature_2_title">Персонализация</string>
<string name="onboarding_access_code_feature_3_description">Код доступа можно восстановить с помощью привязанной карты. Не храните все карты в одном месте</string>
<string name="onboarding_access_code_feature_3_description">Код доступа можно восстановить с помощью привязанной карты. Не храните все карты в одном месте.</string>
<string name="onboarding_access_code_feature_3_title">Восстановление</string>
<string name="onboarding_access_code_hint">Выберите любое слово, фразу или число в качестве кода доступа</string>
<string name="onboarding_access_code_intro_title">Создайте код доступа</string>
<string name="onboarding_access_code_repeat_code_hint">Введите код доступа еще раз, чтобы избежать ошибки</string>
<string name="onboarding_access_code_repeat_code_title">Повторно введите код доступа</string>
<string name="onboarding_access_code_too_short">Код доступа должен состоять не менее чем из 4 символов.</string>
<string name="onboarding_access_codes_doesnt_match">Введенные коды доступа не совпадают</string>
@ -619,6 +623,7 @@
<string name="warning_express_no_exchangeable_coins_title">Нет доступных для обмена токенов</string>
<string name="warning_express_not_enough_fee_for_token_tx_description">Чтобы совершить транзакцию, вам необходимо внести немного %1$s %2$s</string>
<string name="warning_express_not_enough_fee_for_token_tx_title">Невозможно покрыть комиссию %s</string>
<string name="warning_express_notification_invalid_reserve_amount_title">Сумма получения не может быть менее %s</string>
<string name="warning_express_refresh_required_title">Cервис временно недоступен</string>
<string name="warning_express_too_maximum_amount_title">Сумма для обмена должна быть не более %s</string>
<string name="warning_express_too_minimal_amount_title">Сумма для обмена должна быть не менее %s</string>

View file

@ -139,11 +139,9 @@
<string name="main_scan_card_warning_view_subtitle">要訪問所有的網路您需要掃描卡片</string>
<string name="main_scan_card_warning_view_title">掃描卡片</string>
<string name="main_tokens">代幣</string>
<string name="onboarding_access_code_feature_1_description">您必須設置一個單一的訪問代碼來保護您的所有錢包</string>
<string name="onboarding_access_code_feature_1_title">保護</string>
<string name="onboarding_access_code_feature_2_description">您可以稍後在每張卡上設置單獨的訪問密碼</string>
<string name="onboarding_access_code_feature_2_title">個人化</string>
<string name="onboarding_access_code_feature_3_description">門禁密碼可以用聯動卡恢復,不要把所有卡都放在一個地方</string>
<string name="onboarding_access_code_feature_3_title">恢復</string>
<string name="onboarding_access_code_hint">選擇您想要的任何單詞、短語或數字作為您的訪問代碼</string>
<string name="onboarding_access_code_intro_title">建立訪問密碼</string>

View file

@ -182,6 +182,9 @@
<string name="express_choose_providers_subtitle">Tangem offers token swaps via 3rd-party providers according to each provider\'s terms</string>
<string name="express_choose_providers_title">Choose provider</string>
<string name="express_error_code">An error occurred. Code: %s</string>
<string name="express_error_provider_unavailable">Oops! Swapping the selected pair through the chosen provider is temporarily unavailable. Please try again later. (Code:\u00A0%s)</string>
<string name="express_error_swap_pair_unavailable">Selected provider is unavailable at the moment. Please try again later. (Code:\u00A0%s)</string>
<string name="express_error_swap_unavailable">Swaps are unavailable at the moment. Please try again later. (Code:\u00A0%s)</string>
<string name="express_estimated_amount">Estimated amount</string>
<string name="express_exchange_by">Exchange by %s</string>
<string name="express_exchange_notification_failed_text">Visit providers website to refund your money</string>
@ -269,14 +272,15 @@
<string name="manage_tokens_unavailable_vote">Upvote</string>
<string name="manage_tokens_wallet_selector_title">Choose wallet</string>
<string name="manage_tokens_wallet_support_only_one_network_title">The wallet doesn\'t support more than one network</string>
<string name="onboarding_access_code_feature_1_description">You have to set up a single access code to protect all your wallets</string>
<string name="onboarding_access_code_feature_1_description">You have to set up a single access code to protect all your cards</string>
<string name="onboarding_access_code_feature_1_title">Protect</string>
<string name="onboarding_access_code_feature_2_description">You can set up an individual access code on each card later</string>
<string name="onboarding_access_code_feature_2_title">Personalize</string>
<string name="onboarding_access_code_feature_3_description">The access code can be restored with a linked card, don\'t keep all cards in one place</string>
<string name="onboarding_access_code_feature_3_description">The access code can be restored with a linked card. Dont keep all cards at one place.</string>
<string name="onboarding_access_code_feature_3_title">Restore</string>
<string name="onboarding_access_code_hint">Choose any word, phrase, or number you want as your access code</string>
<string name="onboarding_access_code_intro_title">Create Access Code</string>
<string name="onboarding_access_code_repeat_code_hint">Enter your access code one more time to avoid a mistake</string>
<string name="onboarding_access_code_repeat_code_title">Re-enter your Access Code</string>
<string name="onboarding_access_code_too_short">Access code must be at least 4 characters long</string>
<string name="onboarding_access_codes_doesnt_match">Entered access code didn\'t match the initial access code</string>
@ -629,6 +633,7 @@
<string name="warning_express_no_exchangeable_coins_title">No available tokens to swap</string>
<string name="warning_express_not_enough_fee_for_token_tx_description">To make a transaction you need to deposit some %1$s %2$s</string>
<string name="warning_express_not_enough_fee_for_token_tx_title">Unable to cover %s fee</string>
<string name="warning_express_notification_invalid_reserve_amount_title">The amount to receive must be at least %s</string>
<string name="warning_express_refresh_required_title">Service temporarily unavailable</string>
<string name="warning_express_too_maximum_amount_title">The amount of tokens to be swapped must not exceed %s</string>
<string name="warning_express_too_minimal_amount_title">The amount to swap must be at least %s</string>

View file

@ -18,9 +18,11 @@ internal class ErrorsDataConverter(
return when (error.code) {
2010 -> DataError.BadRequest(code = error.code)
2200 -> DataError.SwapsAreUnavailableNowError(code = error.code)
2210 -> DataError.ExchangeProviderNotFoundError(code = error.code)
2220 -> DataError.ExchangeProviderNotActiveError(code = error.code)
2230 -> DataError.ExchangeProviderNotAvailableError(code = error.code)
2231 -> DataError.ExchangeProviderProviderInternalError(code = error.code)
2240 -> DataError.ExchangeNotPossibleError(code = error.code)
2250 -> tryParseExchangeTooSmallAmountError(error = error)
2251 -> tryParseExchangeTooBigAmountError(error = error)

View file

@ -8,12 +8,16 @@ sealed class DataError {
data class BadRequest(override val code: Int) : DataError()
data class SwapsAreUnavailableNowError(override val code: Int) : DataError()
data class ExchangeProviderNotFoundError(override val code: Int) : DataError()
data class ExchangeProviderNotActiveError(override val code: Int) : DataError()
data class ExchangeProviderNotAvailableError(override val code: Int) : DataError()
data class ExchangeProviderProviderInternalError(override val code: Int) : DataError()
data class ExchangeNotPossibleError(override val code: Int) : DataError()
data class ExchangeTooSmallAmountError(override val code: Int, val amount: SwapAmount) : DataError()

View file

@ -0,0 +1,29 @@
package com.tangem.feature.swap.domain.models.ui
import com.tangem.feature.swap.domain.models.DataError
import java.math.BigDecimal
sealed class SwapTransactionState {
data class TxSent(
val fromAmount: String? = null,
val fromAmountValue: BigDecimal? = null,
val toAmount: String? = null,
val toAmountValue: BigDecimal? = null,
val txHash: String,
val txExternalUrl: String? = null,
val timestamp: Long,
) : SwapTransactionState()
data object UserCancelled : SwapTransactionState()
data object BlockchainError : SwapTransactionState()
data object TangemSdkError : SwapTransactionState()
data object NetworkError : SwapTransactionState()
data object UnknownError : SwapTransactionState()
data class ExpressError(val dataError: DataError) : SwapTransactionState()
}

View file

@ -1,22 +0,0 @@
package com.tangem.feature.swap.domain.models.ui
import java.math.BigDecimal
sealed class TxState {
data class TxSent(
val fromAmount: String? = null,
val fromAmountValue: BigDecimal? = null,
val toAmount: String? = null,
val toAmountValue: BigDecimal? = null,
val txHash: String,
val txExternalUrl: String? = null,
val timestamp: Long,
) : TxState()
object UserCancelled : TxState()
object BlockchainError : TxState()
object TangemSdkError : TxState()
object NetworkError : TxState()
object UnknownError : TxState()
}

View file

@ -21,7 +21,7 @@ interface SwapInteractor {
* @param permissionOptions data to give permissions
*/
@Throws(IllegalStateException::class)
suspend fun givePermissionToSwap(networkId: String, permissionOptions: PermissionOptions): TxState
suspend fun givePermissionToSwap(networkId: String, permissionOptions: PermissionOptions): SwapTransactionState
/**
* Find best quote for given tokens to swap
@ -51,7 +51,7 @@ interface SwapInteractor {
* @param currencyToGet [Currency]
* @param amountToSwap amount to swap
* @param fee for tx
* @return [TxState]
* @return [SwapTransactionState]
*/
@Suppress("LongParameterList")
@Throws(IllegalStateException::class)
@ -63,7 +63,7 @@ interface SwapInteractor {
amountToSwap: String,
includeFeeInAmount: IncludeFeeInAmount,
fee: TxFee,
): TxState
): SwapTransactionState
suspend fun updateQuotesStateWithSelectedFee(
state: SwapState.QuotesLoadedState,

View file

@ -197,7 +197,10 @@ internal class SwapInteractorImpl @Inject constructor(
return repository.getPairs(initialCurrency, currenciesList)
}
override suspend fun givePermissionToSwap(networkId: String, permissionOptions: PermissionOptions): TxState {
override suspend fun givePermissionToSwap(
networkId: String,
permissionOptions: PermissionOptions,
): SwapTransactionState {
val derivationPath = permissionOptions.fromToken.network.derivationPath.value
val dataToSign = if (permissionOptions.approveType == SwapApproveType.UNLIMITED) {
getApproveData(
@ -227,16 +230,16 @@ internal class SwapInteractorImpl @Inject constructor(
return when (result) {
is SendTxResult.Success -> {
allowPermissionsHandler.addAddressToInProgress(permissionOptions.forTokenContractAddress)
TxState.TxSent(
SwapTransactionState.TxSent(
txHash = userWalletManager.getLastTransactionHash(networkId, derivationPath).orEmpty(),
timestamp = System.currentTimeMillis(),
)
}
SendTxResult.UserCancelledError -> TxState.UserCancelled
is SendTxResult.BlockchainSdkError -> TxState.BlockchainError
is SendTxResult.TangemSdkError -> TxState.TangemSdkError
is SendTxResult.NetworkError -> TxState.NetworkError
is SendTxResult.UnknownError -> TxState.UnknownError
SendTxResult.UserCancelledError -> SwapTransactionState.UserCancelled
is SendTxResult.BlockchainSdkError -> SwapTransactionState.BlockchainError
is SendTxResult.TangemSdkError -> SwapTransactionState.TangemSdkError
is SendTxResult.NetworkError -> SwapTransactionState.NetworkError
is SendTxResult.UnknownError -> SwapTransactionState.UnknownError
}
}
@ -442,7 +445,7 @@ internal class SwapInteractorImpl @Inject constructor(
amountToSwap: String,
includeFeeInAmount: IncludeFeeInAmount,
fee: TxFee,
): TxState {
): SwapTransactionState {
return when (swapProvider.type) {
ExchangeProviderType.CEX -> {
val amountDecimal = toBigDecimalOrNull(amountToSwap)
@ -519,7 +522,7 @@ internal class SwapInteractorImpl @Inject constructor(
currencyToGet: CryptoCurrency,
amountToSwap: String,
fee: TxFee,
): TxState {
): SwapTransactionState {
val amountDecimal = requireNotNull(toBigDecimalOrNull(amountToSwap)) { "wrong amount format" }
val amount = SwapAmount(amountDecimal, currencyToSend.decimals)
val derivationPath = currencyToSend.network.derivationPath.value
@ -543,7 +546,7 @@ internal class SwapInteractorImpl @Inject constructor(
return when (result) {
is SendTxResult.Success -> {
storeLastCryptoCurrencyId(currencyToGet)
TxState.TxSent(
SwapTransactionState.TxSent(
fromAmount = amountFormatter.formatSwapAmountToUI(
amount,
currencyToSend.symbol,
@ -558,11 +561,11 @@ internal class SwapInteractorImpl @Inject constructor(
timestamp = System.currentTimeMillis(),
)
}
SendTxResult.UserCancelledError -> TxState.UserCancelled
is SendTxResult.BlockchainSdkError -> TxState.BlockchainError
is SendTxResult.TangemSdkError -> TxState.TangemSdkError
is SendTxResult.NetworkError -> TxState.NetworkError
is SendTxResult.UnknownError -> TxState.UnknownError
SendTxResult.UserCancelledError -> SwapTransactionState.UserCancelled
is SendTxResult.BlockchainSdkError -> SwapTransactionState.BlockchainError
is SendTxResult.TangemSdkError -> SwapTransactionState.TangemSdkError
is SendTxResult.NetworkError -> SwapTransactionState.NetworkError
is SendTxResult.UnknownError -> SwapTransactionState.UnknownError
}
}
@ -574,7 +577,7 @@ internal class SwapInteractorImpl @Inject constructor(
txFee: TxFee,
swapProvider: SwapProvider,
userWalletId: UserWalletId,
): TxState {
): SwapTransactionState {
val exchangeData = repository.getExchangeData(
fromContractAddress = currencyToSend.currency.getContractAddress(),
fromNetwork = currencyToSend.currency.network.backendId,
@ -586,15 +589,17 @@ internal class SwapInteractorImpl @Inject constructor(
providerId = swapProvider.providerId,
rateType = RateType.FLOAT,
toAddress = currencyToGet.value.networkAddress?.defaultAddress?.value ?: "",
).getOrNull()
).getOrElse { return SwapTransactionState.ExpressError(it) }
val exchangeDataCex =
exchangeData.transaction as? ExpressTransactionModel.CEX ?: return SwapTransactionState.UnknownError
val exchangeDataCex = exchangeData?.transaction as? ExpressTransactionModel.CEX ?: return TxState.UnknownError
val txExtras = transactionManager.getMemoExtras(
currencyToSend.currency.network.backendId,
exchangeDataCex.txExtraId,
)
if (txExtras == null && exchangeDataCex.txExtraId != null) {
return TxState.UnknownError
return SwapTransactionState.UnknownError
}
val txData = walletManagersFacade.createTransaction(
amount = amount.value.convertToAmount(currencyToSend.currency),
@ -622,11 +627,11 @@ internal class SwapInteractorImpl @Inject constructor(
return result.fold(
ifLeft = {
when (it) {
SendTransactionError.UserCancelledError -> TxState.UserCancelled
is SendTransactionError.BlockchainSdkError -> TxState.BlockchainError
is SendTransactionError.TangemSdkError -> TxState.TangemSdkError
is SendTransactionError.NetworkError -> TxState.NetworkError
else -> TxState.UnknownError
SendTransactionError.UserCancelledError -> SwapTransactionState.UserCancelled
is SendTransactionError.BlockchainSdkError -> SwapTransactionState.BlockchainError
is SendTransactionError.TangemSdkError -> SwapTransactionState.TangemSdkError
is SendTransactionError.NetworkError -> SwapTransactionState.NetworkError
else -> SwapTransactionState.UnknownError
}
},
ifRight = {
@ -643,7 +648,7 @@ internal class SwapInteractorImpl @Inject constructor(
txExternalId = txCexModel?.externalTxId.orEmpty(),
)
storeLastCryptoCurrencyId(currencyToGet.currency)
TxState.TxSent(
SwapTransactionState.TxSent(
fromAmount = amountFormatter.formatSwapAmountToUI(
amount,
currencyToSend.currency.symbol,

View file

@ -926,7 +926,7 @@ internal class StateBuilder(
@Suppress("LongParameterList")
fun createSuccessState(
uiState: SwapStateHolder,
txState: TxState.TxSent,
swapTransactionState: SwapTransactionState.TxSent,
dataState: SwapProcessDataState,
onExploreClick: () -> Unit,
onStatusClick: () -> Unit,
@ -935,8 +935,8 @@ internal class StateBuilder(
val fee = requireNotNull(dataState.selectedFee)
val fromCryptoCurrency = requireNotNull(dataState.fromCryptoCurrency)
val toCryptoCurrency = requireNotNull(dataState.toCryptoCurrency)
val fromAmount = txState.fromAmountValue ?: BigDecimal.ZERO
val toAmount = txState.toAmountValue ?: BigDecimal.ZERO
val fromAmount = swapTransactionState.fromAmountValue ?: BigDecimal.ZERO
val toAmount = swapTransactionState.toAmountValue ?: BigDecimal.ZERO
val providerState = uiState.providerState as ProviderState.Content
val fromFiatAmount = getFormattedFiatAmount(fromCryptoCurrency.value.fiatRate?.multiply(fromAmount))
@ -944,7 +944,7 @@ internal class StateBuilder(
return uiState.copy(
successState = SwapSuccessStateHolder(
timestamp = txState.timestamp,
timestamp = swapTransactionState.timestamp,
txUrl = txUrl,
providerName = stringReference(providerState.name),
providerType = stringReference(providerState.type),
@ -952,8 +952,8 @@ internal class StateBuilder(
providerIcon = providerState.iconUrl,
rate = providerState.subtitle,
fee = stringReference("${fee.feeCryptoFormatted} (${fee.feeFiatFormatted})"),
fromTokenAmount = stringReference(txState.fromAmount.orEmpty()),
toTokenAmount = stringReference(txState.toAmount.orEmpty()),
fromTokenAmount = stringReference(swapTransactionState.fromAmount.orEmpty()),
toTokenAmount = stringReference(swapTransactionState.toAmount.orEmpty()),
fromTokenFiatAmount = stringReference(fromFiatAmount),
toTokenFiatAmount = stringReference(toFiatAmount),
fromTokenIconState = iconStateConverter.convert(fromCryptoCurrency),
@ -964,17 +964,50 @@ internal class StateBuilder(
)
}
fun createErrorTransaction(uiState: SwapStateHolder, txState: TxState, onAlertClick: () -> Unit): SwapStateHolder {
fun createErrorTransaction(
uiState: SwapStateHolder,
swapTransactionState: SwapTransactionState,
onAlertClick: () -> Unit,
): SwapStateHolder {
return uiState.copy(
alert = SwapWarning.GenericWarning(
message = null,
message = if (swapTransactionState is SwapTransactionState.ExpressError) {
getAlertErrorMessage(swapTransactionState.dataError)
} else {
null
},
onClick = onAlertClick,
type = if (txState is TxState.NetworkError) GenericWarningType.NETWORK else GenericWarningType.OTHER,
type = if (swapTransactionState is SwapTransactionState.NetworkError) {
GenericWarningType.NETWORK
} else {
GenericWarningType.OTHER
},
),
changeCardsButtonState = ChangeCardsButtonState.ENABLED,
)
}
private fun getAlertErrorMessage(dataError: DataError): TextReference? {
return when (dataError) {
is DataError.SwapsAreUnavailableNowError -> resourceReference(
id = R.string.express_error_swap_unavailable,
formatArgs = wrappedList(dataError.code),
)
is DataError.ExchangeNotPossibleError -> resourceReference(
id = R.string.express_error_provider_unavailable,
formatArgs = wrappedList(dataError.code),
)
is DataError.ExchangeProviderNotActiveError,
is DataError.ExchangeProviderNotAvailableError,
is DataError.ExchangeProviderProviderInternalError,
-> resourceReference(
id = R.string.express_error_swap_pair_unavailable,
formatArgs = wrappedList(dataError.code),
)
else -> null
}
}
fun createAlert(
uiState: SwapStateHolder,
isPriceImpact: Boolean,

View file

@ -283,7 +283,7 @@ private fun Content(
if (amountEquivalent != null) {
if (type is TransactionCardType.ReadOnly) {
Row {
Row(modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size20)) {
if (priceImpact is PriceImpact.Value) {
Text(
text = makePriceImpactBalanceWarning(
@ -293,7 +293,6 @@ private fun Content(
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.body2,
modifier = Modifier
.defaultMinSize(minHeight = TangemTheme.dimens.size20)
.align(Alignment.CenterVertically),
)
} else {
@ -302,7 +301,6 @@ private fun Content(
text = it,
color = TangemTheme.colors.text.tertiary,
style = TangemTheme.typography.body2,
modifier = Modifier.defaultMinSize(minHeight = TangemTheme.dimens.size20),
)
}
}
@ -564,7 +562,7 @@ private fun TransactionCardPreview() {
@Suppress("MagicNumber")
private fun TransactionCardPreviewWithPriceImpact() {
TransactionCard(
type = TransactionCardType.ReadOnly(),
type = TransactionCardType.ReadOnly(showWarning = true),
amountEquivalent = "1 000 000",
tokenIconUrl = "",
tokenCurrency = "DAI",

View file

@ -503,7 +503,7 @@ internal class SwapViewModel @Inject constructor(
)
}.onSuccess {
when (it) {
is TxState.TxSent -> {
is SwapTransactionState.TxSent -> {
sendSuccessSwapEvent(fromCurrency.currency, fee.feeType)
val url = blockchainInteractor.getExplorerTransactionLink(
networkId = fromCurrency.currency.network.backendId,
@ -512,7 +512,7 @@ internal class SwapViewModel @Inject constructor(
updateWalletBalance()
uiState = stateBuilder.createSuccessState(
uiState = uiState,
txState = it,
swapTransactionState = it,
dataState = dataState,
txUrl = url,
onExploreClick = {
@ -537,7 +537,7 @@ internal class SwapViewModel @Inject constructor(
swapRouter.openScreen(SwapNavScreen.Success)
}
is TxState.UserCancelled -> {
is SwapTransactionState.UserCancelled -> {
startLoadingQuotesFromLastState()
}
else -> {
@ -604,14 +604,14 @@ internal class SwapViewModel @Inject constructor(
)
}.onSuccess {
when (it) {
is TxState.TxSent -> {
is SwapTransactionState.TxSent -> {
sendApproveSuccessEvent(fromToken, feeForPermission.feeType, approveType)
updateWalletBalance()
uiState = stateBuilder.loadingPermissionState(uiState)
uiState = stateBuilder.dismissBottomSheet(uiState)
startLoadingQuotesFromLastState(isSilent = true)
}
is TxState.UserCancelled -> Unit
is SwapTransactionState.UserCancelled -> Unit
else -> {
uiState = stateBuilder.createErrorTransaction(uiState, it) {
uiState = stateBuilder.clearAlert(uiState)

View file

@ -19,7 +19,6 @@ import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.R
import com.tangem.core.ui.components.inputrow.InputRowBestRate
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.res.TangemTheme
@Composable
@ -68,7 +67,7 @@ internal fun ExchangeProvider(
)
Text(
modifier = Modifier.align(Alignment.CenterVertically),
text = stringResource(R.string.express_transaction_id, wrappedList(providerTxId)),
text = stringResource(R.string.express_transaction_id, providerTxId),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.tertiary,
)