Updated on 2026-08-14

This commit is contained in:
Tangem 2025-06-09 12:15:22 +02:00
parent b699b723a8
commit b17d61bd7f
13 changed files with 146 additions and 35 deletions

@ -1 +1 @@
Subproject commit 4ec5de66321afa82c04104746015ea9e6bc9fe64
Subproject commit d1f1bdcca80c2b1f1b53f331fcb0ce78e76d5615

View file

@ -5,7 +5,7 @@
},
{
"name": "ONRAMP_ENABLED",
"version": "5.24.1"
"version": "5.24.2"
},
{
"name": "VISA_ONBOARDING_ENABLED",

View file

@ -114,6 +114,7 @@
<string name="common_cancel">Abbrechen</string>
<string name="common_change">Ändern</string>
<string name="common_choose_action">Aktion wählen</string>
<string name="common_choose_network">Netzwerk auswählen</string>
<string name="common_choose_token">Token auswählen</string>
<string name="common_claim">Beanspruchen</string>
<string name="common_claim_rewards">Stakingbelohnungen beanspruchen</string>

View file

@ -112,6 +112,7 @@
<string name="common_cancel">キャンセル</string>
<string name="common_change">変更</string>
<string name="common_choose_action">アクションを選択</string>
<string name="common_choose_network">ネットワークを選択</string>
<string name="common_choose_token">トークンを選択</string>
<string name="common_claim">請求</string>
<string name="common_claim_rewards">報酬を受け取る</string>
@ -332,6 +333,7 @@
<string name="express_more_providers_soon">さらに多くのプロバイダーが利用可能になる予定です</string>
<string name="express_provider">プロバイダー</string>
<string name="express_provider_best_rate">ベストレート</string>
<string name="express_provider_fca_warning_list">FCA警告リスト</string>
<string name="express_provider_max_amount">最大 %s まで使用可能</string>
<string name="express_provider_min_amount">%s 以上で利用可能</string>
<string name="express_provider_not_available">このペアは利用できません</string>
@ -343,6 +345,8 @@
<string name="express_status_hide_button_text">この取引を非表示にする</string>
<string name="express_status_hide_dialog_text">一度非表示にすると、取引状況を再度表示することはできません。代わりに、スワイプして閉じることができます。</string>
<string name="express_status_hide_dialog_title">取引状況を非表示にしますか?</string>
<string name="express_swap_not_supported_text">このトークンはサポートされていません。別のトークンを選択してスワップしてください。</string>
<string name="express_swap_not_supported_title">%sはサポートされていません</string>
<string name="express_swap_with">スワップする</string>
<string name="express_token_list_empty_search">トークンが見つかりません。別のリクエストをお試しください。</string>
<string name="express_transaction_id">ID: %s</string>
@ -864,6 +868,7 @@
<string name="settings_forget_wallet">ウォレット削除</string>
<string name="settings_forget_wallet_footer">これにより、ウォレットがアプリから削除されます。ウォレットは再度追加できます。</string>
<string name="settings_wallet_name_title">名前</string>
<string name="stake_token_description">このトークンのステーキングに参加</string>
<string name="staking_amount_requirement_error">ステーキング金額は %s 以上である必要があります</string>
<string name="staking_amount_tron_integer_error">ネットワークルールにより、ステーキング金額は%1$s TRX に切り上げられます。</string>
<string name="staking_amount_tron_integer_error_unstaking">ネットワークルールにより、ステーキング解除の量は%1$s TRX に切り上げられます。</string>
@ -998,6 +1003,7 @@
<string name="story_web3_title">Web3.0対応</string>
<string name="sui_not_enough_coin_for_fee_description">続行するには少なくとも%1$sの受信取引が必要です</string>
<string name="sui_not_enough_coin_for_fee_title">残高不足</string>
<string name="swap_fixed_rate">固定レート</string>
<string name="swap_give_permission_fee_footer">ネットワークは、あなたがトークンのスワップを承認していることを確認するために、トークン承認手数料を請求します。</string>
<string name="swap_promo_text">より多くのトークンをより良いレートで、ウォレット内にて直接交換します。</string>
<string name="swap_promo_title">新しいスワッププロバイダーが利用可能になりました!</string>
@ -1205,6 +1211,8 @@
<string name="warning_express_notification_invalid_reserve_amount_title">受け取る金額は、 %s 以上である必要があります。</string>
<string name="warning_express_pair_unavailable_message">これは、選択したペアがプロバイダーでは現在交換できないために発生する可能性があります。しばらく待ってからもう一度お試しください。(コード%s )</string>
<string name="warning_express_pair_unavailable_title">選択されたペアは一時的に利用できません</string>
<string name="warning_express_providers_fca_warning_description">一部のプロバイダーは英国金融行動監視機構FCAの認可を受けていません。そのようなプロバイダーとの取引は避けるべきです。</string>
<string name="warning_express_providers_fca_warning_title">FCA警告リスト</string>
<string name="warning_express_refresh_required_title">サービスは一時的に利用できません</string>
<string name="warning_express_too_maximum_amount_title">スワップするトークンの量は %s を超えないでください</string>
<string name="warning_express_too_minimal_amount_title">スワップ金額は %s 以上である必要があります</string>
@ -1239,7 +1247,7 @@
<string name="warning_rate_app_message">あなたのレビューは、Tangemウォレットをさらに良くするためのモチベーションになります</string>
<string name="warning_rate_app_title">Tangemを楽しんでいますか?</string>
<string name="warning_receive_blocked_hedera_token_association_required_message">トークンを受け取る前に、トークンを関連付ける必要があります。</string>
<string name="warning_receive_blocked_stelar_token_trustline_required_message">トークンを受け取る前にトラストラインを開く必要があります</string>
<string name="warning_receive_blocked_stelar_token_trustline_required_message">トークンを受け取る前にトラストラインを開く必要があります</string>
<string name="warning_rent_fee_title">ネットワーク使用料が必要です</string>
<string name="warning_seedphrase_action_required_title">対応が必要です</string>
<string name="warning_seedphrase_contacted_support">ウォレットの作成後、7日以内にアプリ経由でサポートに連絡しましたか連絡した場合、あるいは連絡したかわからない場合は、「はい」をクリックして指示に従ってください。</string>
@ -1255,9 +1263,10 @@
<string name="warning_some_networks_unreachable_message">下にスワイプして更新するか、後でもう一度お試しください。</string>
<string name="warning_some_networks_unreachable_title">一部のネットワークにアクセスできません</string>
<string name="warning_some_token_balances_not_updated">一部のトークン残高を更新できませんでした</string>
<string name="warning_stelar_token_required_min_coin_reserve">必要な最低XLMリザーブ %1$s</string>
<string name="warning_stellar_token_trustline_button_title">トラストラインを開く</string>
<string name="warning_stellar_token_trustline_tiile">トラストラインタイトルを開く</string>
<string name="warning_stelar_token_required_min_coin_reserve">%1$sが足りません。このトークンを関連付けるには、XLMアカウントにチャージしてください。</string>
<string name="warning_stellar_token_trustline_button_title">トラストラインを有効にする</string>
<string name="warning_stellar_token_trustline_subtiile">ネットワークルールに従い、このトークンを入金する前にトラストラインを開設する必要があります。これにより、ウォレットが資産を受け入れ、保管できるようになります。</string>
<string name="warning_stellar_token_trustline_tiile">このトークンのトラストラインを有効にする</string>
<string name="warning_testnet_card_message">これはテストネットカードです。取引処理はできませんので、テストおよび開発目的でのみご利用ください。</string>
<string name="warning_testnet_card_title">テスト目的のみ</string>
<string name="warning_token_balance_not_updated">残高が古い可能性があります。ページを更新してください。</string>
@ -1281,8 +1290,10 @@
<string name="wc_allow_to_spend">使用を許可する</string>
<string name="wc_common_address">アドレス</string>
<string name="wc_common_connect">接続する</string>
<string name="wc_common_loading">読み込み中</string>
<string name="wc_common_network">ネットワーク</string>
<string name="wc_common_networks">ネットワーク</string>
<string name="wc_common_unlimited">無制限</string>
<string name="wc_common_wallet">ウォレット</string>
<string name="wc_connected_networks">接続されたネットワーク</string>
<string name="wc_connection_reqeust_can_view_balance">ウォレットの残高とアクティビティを表示する</string>
@ -1299,6 +1310,7 @@
<string name="wc_disconnect_all_alert_desc">すべてのdAppsの接続解除に関するテキスト</string>
<string name="wc_disconnect_all_alert_title">すべてのdAppを接続解除する</string>
<string name="wc_estimated_wallet_changes">ウォレットの変更の予測</string>
<string name="wc_estimated_wallet_changes_not_simulated">取引をシミュレーションできませんでした。注意して続行してください。</string>
<string name="wc_malicious_transaction">悪意のある取引</string>
<string name="wc_missing_required_network_description">このウォレットのプロフィールに%sネットワークを追加する</string>
<string name="wc_missing_required_network_title">ウォレットに必要なネットワークはありません</string>

View file

@ -112,6 +112,7 @@
<string name="common_cancel">Отмена</string>
<string name="common_change">Изменить</string>
<string name="common_choose_action">Выберите действие</string>
<string name="common_choose_network">Выберите сеть</string>
<string name="common_choose_token">Выберите токен</string>
<string name="common_claim">Получить</string>
<string name="common_claim_rewards">Вывести награду</string>

View file

@ -114,6 +114,7 @@
<string name="common_cancel">Cancel</string>
<string name="common_change">Change</string>
<string name="common_choose_action">Choose action</string>
<string name="common_choose_network">Choose network</string>
<string name="common_choose_token">Choose token</string>
<string name="common_claim">Claim</string>
<string name="common_claim_rewards">Claim rewards</string>
@ -289,6 +290,7 @@
<string name="exchange_tokens_unavailable_tokens_header">Cannot be swapped for %s</string>
<string name="express_by_provider">Provided by</string>
<string name="express_cex_status_button_title">Status</string>
<string name="express_choose_provider">Choose provider</string>
<string name="express_choose_providers_subtitle">Providers facilitate transactions</string>
<string name="express_choose_providers_title">Provider</string>
<string name="express_error_code">An error occurred. Code: %s</string>
@ -349,6 +351,8 @@
<string name="express_status_hide_button_text">Hide this transaction</string>
<string name="express_status_hide_dialog_text">Once hidden, the transaction status cannot be viewed again. You can simply swipe to dismiss instead.</string>
<string name="express_status_hide_dialog_title">Hide Transaction Status?</string>
<string name="express_swap_not_supported_text">This token is not supported. Please choose a different token to swap.</string>
<string name="express_swap_not_supported_title">%s is not supported</string>
<string name="express_swap_with">Swap with</string>
<string name="express_token_list_empty_search">No tokens found. Please try another request</string>
<string name="express_transaction_id">ID: %s</string>
@ -864,7 +868,6 @@
<string name="send_summary_transaction_description_suffix_fee_covered">network fee will be covered by using %1$s energy</string>
<string name="send_summary_transaction_description_suffix_fee_reduced">network fee will be reduced by spending %1$s energy</string>
<string name="send_summary_transaction_description_suffix_including">including a network fee of %1$s</string>
<string name="send_test_alert_title">asdflkdsl;kfasl;fn;lnf asdjfnasdk;jf dfk;jasdjf;kajsdnf</string>
<string name="send_transaction_success">Transaction has been successfully signed and sent to the blockchain node. Wallet balance will be updated in a while</string>
<string name="send_tron_account_activation_error">%1$s is an asset in the Tron network. To calculate the fee and make a transaction you need to deposit some Tron (TRX) in your account.</string>
<string name="send_validation_amount_exceeds_balance">Amount exceeds balance</string>
@ -880,6 +883,7 @@
<string name="settings_forget_wallet">Forget wallet</string>
<string name="settings_forget_wallet_footer">This will remove the wallet from the application. The wallet itself can be added again.</string>
<string name="settings_wallet_name_title">Name</string>
<string name="stake_token_description">Join staking with this token</string>
<string name="staking_amount_requirement_error">The amount to stake must be at least %s</string>
<string name="staking_amount_tron_integer_error">Staking amount will be rounded to %1$s TRX due to network rules.</string>
<string name="staking_amount_tron_integer_error_unstaking">Unstaking amount will be rounded to %1$s TRX due to network rules.</string>
@ -1014,6 +1018,7 @@
<string name="story_web3_title">Web 3.0 Compatible</string>
<string name="sui_not_enough_coin_for_fee_description">An incoming transaction of at least %1$s is required to proceed</string>
<string name="sui_not_enough_coin_for_fee_title">Insufficient funds</string>
<string name="swap_fixed_rate">Fixed Rate</string>
<string name="swap_give_permission_fee_footer">The network will charge a token approval fee to verify that you are authorizing the use of your token for the swap.</string>
<string name="swap_promo_text">Exchange more tokens at better rates directly in your wallet.</string>
<string name="swap_promo_title">New Swap Provider Available!</string>
@ -1337,6 +1342,7 @@
<string name="wc_alert_domain_issues_description">This domain cannot be verified. Check the request carefully approving.</string>
<string name="wc_alert_session_disconnected_description">Please return to your browser and reconnect via WalletConnect.</string>
<string name="wc_alert_session_disconnected_title">WalletConnect session was disconnected</string>
<string name="wc_alert_sign_anyway">Sign anyway</string>
<string name="wc_alert_unknown_error_description">Error code: %s. If the problem persists — feel free to contact our support.</string>
<string name="wc_alert_unknown_error_title">We\'ve encountered unknown error</string>
<string name="wc_alert_unsupported_method_description">Error code: 8 005. If the problem persists — feel free to contact our support.</string>

View file

@ -485,6 +485,7 @@ internal class SwapModel @Inject constructor(
expressDataError = state.error,
includeFeeInAmount = state.includeFeeInAmount,
isReverseSwapPossible = isReverseSwapPossible(),
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
)
sendErrorAnalyticsEvent(state.error, provider)
}
@ -1102,6 +1103,7 @@ internal class SwapModel @Inject constructor(
selectedProviderId = providerId,
pricesLowerBest = pricesLowerBest,
providersStates = dataState.lastLoadedSwapStates,
needApplyFCARestrictions = userCountry.needApplyFCARestrictions(),
) { uiState = stateBuilder.dismissBottomSheet(uiState) }
},
onProviderSelect = {

View file

@ -1,9 +1,11 @@
package com.tangem.feature.swap.models.states
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
import kotlinx.collections.immutable.ImmutableList
data class ChooseProviderBottomSheetConfig(
val selectedProviderId: String,
val providers: ImmutableList<ProviderState>,
val notification: NotificationUM?,
) : TangemBottomSheetConfigContent

View file

@ -44,6 +44,7 @@ sealed class ProviderState {
@Immutable
sealed class AdditionalBadge {
data object FCAWarningList : AdditionalBadge()
data object BestTrade : AdditionalBadge()
data object Empty : AdditionalBadge()
data object PermissionRequired : AdditionalBadge()

View file

@ -99,6 +99,12 @@ internal object SwapNotificationUM {
subtitle = resourceReference(R.string.warning_express_wrong_amount_description),
iconResId = R.drawable.ic_alert_circle_24,
)
data object FCAWarningList : Error(
title = resourceReference(R.string.warning_express_providers_fca_warning_title),
subtitle = resourceReference(R.string.warning_express_providers_fca_warning_description),
iconResId = R.drawable.ic_alert_circle_24,
)
}
sealed class Warning(

View file

@ -14,8 +14,11 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.stringResourceSafe
@ -47,17 +50,32 @@ private fun ChooseProviderBottomSheetContent(content: ChooseProviderBottomSheetC
style = TangemTheme.typography.caption2,
color = TangemTheme.colors.text.secondary,
modifier = Modifier
.padding(top = TangemTheme.dimens.spacing10)
.padding(
top = 10.dp,
bottom = 16.dp,
)
.padding(horizontal = TangemTheme.dimens.spacing56),
textAlign = TextAlign.Center,
)
if (content.notification != null) {
Notification(
config = content.notification.config,
modifier = Modifier
.padding(
start = 16.dp,
end = 16.dp,
bottom = 12.dp,
),
iconTint = TangemTheme.colors.icon.warning,
)
}
Column(
modifier = Modifier
.padding(
top = TangemTheme.dimens.spacing16,
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing14,
start = 16.dp,
end = 16.dp,
bottom = 14.dp,
)
.background(
color = TangemTheme.colors.background.action,
@ -129,6 +147,10 @@ private fun Preview_ChooseProviderBottomSheet() {
)
val content = ChooseProviderBottomSheetConfig(
selectedProviderId = "1",
notification = NotificationUM.Error(
title = resourceReference(R.string.warning_express_providers_fca_warning_title),
subtitle = resourceReference(R.string.warning_express_providers_fca_warning_description),
),
providers = providers,
)
TangemThemePreview {

View file

@ -145,6 +145,7 @@ private fun ProviderContentState(
}
val badgeModifier = Modifier.padding(start = TangemTheme.dimens.spacing4)
when (state.additionalBadge) {
ProviderState.AdditionalBadge.FCAWarningList -> FCABadgeItem(badgeModifier)
ProviderState.AdditionalBadge.BestTrade -> BestTradeItem(badgeModifier)
ProviderState.AdditionalBadge.PermissionRequired -> PermissionBadgeItem(badgeModifier)
ProviderState.AdditionalBadge.Recommended -> RecommendedItem(badgeModifier)
@ -361,6 +362,7 @@ private fun BestTradeItem(modifier: Modifier = Modifier) {
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.icon.accent,
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing6),
maxLines = 1,
)
}
}
@ -378,6 +380,25 @@ private fun PermissionBadgeItem(modifier: Modifier = Modifier) {
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing6),
maxLines = 1,
)
}
}
@Composable
private fun FCABadgeItem(modifier: Modifier = Modifier) {
Box(
modifier = modifier.background(
color = TangemTheme.colors.background.secondary,
shape = TangemTheme.shapes.roundedCornersLarge,
),
) {
Text(
text = stringResourceSafe(id = R.string.express_provider_fca_warning_list),
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.text.tertiary,
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing6),
maxLines = 1,
)
}
}
@ -395,6 +416,7 @@ private fun RecommendedItem(modifier: Modifier = Modifier) {
style = TangemTheme.typography.caption1,
color = TangemTheme.colors.icon.accent,
modifier = Modifier.padding(horizontal = TangemTheme.dimens.spacing6),
maxLines = 1,
)
}
}

View file

@ -347,13 +347,13 @@ internal class StateBuilder(
ChangeCardsButtonState.DISABLED
},
providerState = swapProvider.convertToContentClickableProviderState(
needApplyFCARestrictions = needApplyFCARestrictions,
isBestRate = bestRatedProviderId == swapProvider.providerId,
fromTokenInfo = quoteModel.fromTokenInfo,
toTokenInfo = quoteModel.toTokenInfo,
isNeedBestRateBadge = isNeedBestRateBadge,
selectionType = ProviderState.SelectionType.CLICK,
onProviderClick = actions.onProviderClick,
needApplyFCARestrictions = needApplyFCARestrictions,
),
priceImpact = if (quoteModel.priceImpact.value > PRICE_IMPACT_THRESHOLD) {
quoteModel.priceImpact
@ -411,6 +411,7 @@ internal class StateBuilder(
includeFeeInAmount: IncludeFeeInAmount,
expressDataError: ExpressDataError,
isReverseSwapPossible: Boolean,
needApplyFCARestrictions: Boolean,
): SwapStateHolder {
if (uiStateHolder.sendCardData !is SwapCardState.SwapCardData) return uiStateHolder
if (uiStateHolder.receiveCardData !is SwapCardState.SwapCardData) return uiStateHolder
@ -427,6 +428,7 @@ internal class StateBuilder(
expressDataError = expressDataError,
onProviderClick = actions.onProviderClick,
selectionType = ProviderState.SelectionType.CLICK,
needApplyFCARestrictions = needApplyFCARestrictions,
)
val receiveCardData = toToken?.let {
SwapCardState.SwapCardData(
@ -477,12 +479,14 @@ internal class StateBuilder(
)
}
@Suppress("LongParameterList")
private fun getProviderStateForError(
swapProvider: SwapProvider,
fromToken: CryptoCurrency,
expressDataError: ExpressDataError,
onProviderClick: (String) -> Unit,
selectionType: ProviderState.SelectionType,
needApplyFCARestrictions: Boolean,
): ProviderState {
return when (expressDataError) {
is ExpressDataError.ExchangeTooSmallAmountError -> {
@ -494,6 +498,7 @@ internal class StateBuilder(
),
selectionType = selectionType,
onProviderClick = onProviderClick,
needApplyFCARestrictions = needApplyFCARestrictions,
)
}
is ExpressDataError.ExchangeTooBigAmountError -> {
@ -505,6 +510,7 @@ internal class StateBuilder(
),
selectionType = selectionType,
onProviderClick = onProviderClick,
needApplyFCARestrictions = needApplyFCARestrictions,
)
}
else -> {
@ -991,17 +997,27 @@ internal class StateBuilder(
selectedProviderId: String,
pricesLowerBest: Map<String, Float>,
providersStates: Map<SwapProvider, SwapState>,
needApplyFCARestrictions: Boolean,
onDismiss: () -> Unit,
): SwapStateHolder {
val availableProvidersStates = providersStates.entries
.mapNotNull {
it.convertToProviderBottomSheetState(pricesLowerBest, actions.onProviderSelect)
it.convertToProviderBottomSheetState(
pricesLowerBest = pricesLowerBest,
onProviderSelect = actions.onProviderSelect,
needApplyFCARestrictions = needApplyFCARestrictions,
)
}
.sortedWith(ProviderPercentDiffComparator)
.toImmutableList()
val isAnyFCABadge = availableProvidersStates.any {
(it as? ProviderState.Content)?.additionalBadge == ProviderState.AdditionalBadge.FCAWarningList
}
val config = ChooseProviderBottomSheetConfig(
selectedProviderId = selectedProviderId,
providers = availableProvidersStates,
notification = SwapNotificationUM.Error.FCAWarningList.takeIf { isAnyFCABadge },
)
return uiState.copy(
bottomSheetConfig = TangemBottomSheetConfig(
@ -1109,6 +1125,7 @@ internal class StateBuilder(
private fun Map.Entry<SwapProvider, SwapState>.convertToProviderBottomSheetState(
pricesLowerBest: Map<String, Float>,
onProviderSelect: (String) -> Unit,
needApplyFCARestrictions: Boolean,
): ProviderState? {
val provider = this.key
return when (val state = this.value) {
@ -1119,6 +1136,7 @@ internal class StateBuilder(
onProviderClick = onProviderSelect,
pricesLowerBest = pricesLowerBest,
selectionType = ProviderState.SelectionType.SELECT,
needApplyFCARestrictions = needApplyFCARestrictions,
)
}
is SwapState.SwapError -> getProviderStateForError(
@ -1127,6 +1145,7 @@ internal class StateBuilder(
expressDataError = state.error,
onProviderClick = onProviderSelect,
selectionType = ProviderState.SelectionType.SELECT,
needApplyFCARestrictions = needApplyFCARestrictions,
)
}
}
@ -1143,13 +1162,13 @@ internal class StateBuilder(
@Suppress("LongParameterList")
private fun SwapProvider.convertToContentClickableProviderState(
needApplyFCARestrictions: Boolean,
isBestRate: Boolean,
fromTokenInfo: TokenSwapInfo,
toTokenInfo: TokenSwapInfo,
selectionType: ProviderState.SelectionType,
isNeedBestRateBadge: Boolean,
onProviderClick: (String) -> Unit,
needApplyFCARestrictions: Boolean,
): ProviderState {
val rate = toTokenInfo.tokenAmount.value.calculateRate(
fromTokenInfo.tokenAmount.value,
@ -1161,21 +1180,21 @@ internal class StateBuilder(
append("")
append(rate.format { crypto(toTokenInfo.cryptoCurrencyStatus.currency) })
}
// val rateString = "1 $fromCurrencySymbol ≈ $rate $toCurrencySymbol"
val badge = if (isRecommended) {
ProviderState.AdditionalBadge.Recommended
} else if (isNeedBestRateBadge && isBestRate && !needApplyFCARestrictions) {
ProviderState.AdditionalBadge.BestTrade
} else {
ProviderState.AdditionalBadge.Empty
val additionalBadge = when {
needApplyFCARestrictions && isFCARestrictedProvider() -> ProviderState.AdditionalBadge.FCAWarningList
isRecommended -> ProviderState.AdditionalBadge.Recommended
isNeedBestRateBadge && isBestRate && !needApplyFCARestrictions -> ProviderState.AdditionalBadge.BestTrade
else -> ProviderState.AdditionalBadge.Empty
}
return ProviderState.Content(
id = this.providerId,
name = this.name,
iconUrl = this.imageLarge,
type = this.type.providerName,
subtitle = stringReference(rateString),
additionalBadge = badge,
additionalBadge = additionalBadge,
selectionType = selectionType,
percentLowerThenBest = PercentDifference.Empty,
namePrefix = ProviderState.PrefixType.NONE,
@ -1188,16 +1207,20 @@ internal class StateBuilder(
selectionType: ProviderState.SelectionType,
pricesLowerBest: Map<String, Float>,
onProviderClick: (String) -> Unit,
needApplyFCARestrictions: Boolean,
): ProviderState {
val toTokenInfo = state.toTokenInfo
val rateString = toTokenInfo.tokenAmount.getFormattedCryptoAmount(toTokenInfo.cryptoCurrencyStatus.currency)
val additionalBadge = if (state.permissionState is PermissionDataState.PermissionReadyForRequest) {
ProviderState.AdditionalBadge.PermissionRequired
} else if (isRecommended) {
ProviderState.AdditionalBadge.Recommended
} else {
ProviderState.AdditionalBadge.Empty
val additionalBadge = when {
needApplyFCARestrictions && isFCARestrictedProvider() -> ProviderState.AdditionalBadge.FCAWarningList
state.permissionState is PermissionDataState.PermissionReadyForRequest -> {
ProviderState.AdditionalBadge.PermissionRequired
}
isRecommended -> ProviderState.AdditionalBadge.Recommended
else -> ProviderState.AdditionalBadge.Empty
}
return ProviderState.Content(
id = this.providerId,
name = this.name,
@ -1219,12 +1242,14 @@ internal class StateBuilder(
alertText: TextReference,
selectionType: ProviderState.SelectionType,
onProviderClick: (String) -> Unit,
needApplyFCARestrictions: Boolean,
): ProviderState {
val additionalBadge = if (swapProvider.isRecommended) {
ProviderState.AdditionalBadge.Recommended
} else {
ProviderState.AdditionalBadge.Empty
val additionalBadge = when {
needApplyFCARestrictions && isFCARestrictedProvider() -> ProviderState.AdditionalBadge.FCAWarningList
swapProvider.isRecommended -> ProviderState.AdditionalBadge.Recommended
else -> ProviderState.AdditionalBadge.Empty
}
return ProviderState.Content(
id = this.providerId,
name = this.name,
@ -1272,6 +1297,10 @@ internal class StateBuilder(
return "$TILDE_SIGN $this"
}
private fun SwapProvider.isFCARestrictedProvider(): Boolean {
return FCA_RESTRICTED_PROVIDER_IDS.contains(providerId)
}
private companion object {
private const val RU_LOCALE = "ru"
private const val EN_LOCALE = "en"
@ -1282,7 +1311,14 @@ internal class StateBuilder(
private const val MAX_DECIMALS_TO_SHOW = 8
private const val IF_ZERO_DECIMALS_TO_SHOW = 2
private const val FEE_READ_MORE_URL_FIRST_PART = "https://tangem.com/"
private const val FEE_READ_MORE_URL_SECOND_PART =
"/blog/post/what-is-a-transaction-fee-and-why-do-we-need-it/"
private const val FEE_READ_MORE_URL_SECOND_PART = "/blog/post/what-is-a-transaction-fee-and-why-do-we-need-it/"
private val FCA_RESTRICTED_PROVIDER_IDS = setOf(
"changelly",
"changenow",
"okx-cross-chain",
"okx-on-chain",
"simpleswap",
)
}
}