Updated on 2026-08-14

This commit is contained in:
Tangem 2025-09-17 15:41:40 +03:00
parent c45301b490
commit 380e7ef082
12 changed files with 108 additions and 24 deletions

View file

@ -23,6 +23,15 @@ internal object OnrampDomainModule {
return GetOnrampCurrenciesUseCase(onrampRepository, onrampErrorResolver)
}
@Provides
@Singleton
fun provideGetOnrampCurrencyUseCase(
onrampRepository: OnrampRepository,
onrampErrorResolver: OnrampErrorResolver,
): OnrampGetDefaultCurrencyUseCase {
return OnrampGetDefaultCurrencyUseCase(onrampRepository, onrampErrorResolver)
}
@Provides
@Singleton
fun provideOnrampSaveDefaultCurrencyUseCase(

View file

@ -15,9 +15,10 @@ internal object PromoDomainModule {
@Provides
@Singleton
fun provideShouldShowSwapPromoWalletUseCase(
promoSettingsRepository: PromoRepository,
promoRepository: PromoRepository,
settingsRepository: SettingsRepository,
): ShouldShowPromoWalletUseCase {
return ShouldShowPromoWalletUseCase(promoSettingsRepository)
return ShouldShowPromoWalletUseCase(promoRepository, settingsRepository)
}
@Provides

View file

@ -644,6 +644,8 @@
<string name="notification_referral_promo_button">Присоединиться</string>
<string name="notification_referral_promo_text">Поделись промокодом — заработай 5 USDT с каждой покупки. Твои друзья получат скидку 10% на карту Tangem!</string>
<string name="notification_referral_promo_title">Получай бонусы за каждого друга!</string>
<string name="notification_sepa_text">Tangem снижает комиссии SEPA почти до нуля, предлагая вам лучшие условия.</string>
<string name="notification_sepa_title">Покупайте криптовалюту без комиссии!</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>

View file

@ -512,18 +512,18 @@
<string name="hot_access_code_set_biometric_ask">Do you want to allow “Tangem” to use biometric authentication? To confirm your identity and open the app</string>
<string name="hot_crypto_add_token_subtitle">to %s</string>
<string name="hot_crypto_token_network">On %s network</string>
<string name="hw_access_code_create_alert_title">Are you sure you want to exit the access code creation process?</string>
<string name="hw_access_code_create_alert_title">Are you sure you want to cancel access code setup?</string>
<string name="hw_activation_need_backup">Backup Now</string>
<string name="hw_activation_need_description">To complete setup, back up your wallet and secure app access with a Access Code.</string>
<string name="hw_activation_need_finish">Finish Now</string>
<string name="hw_activation_need_title">Finish Wallet Activation</string>
<string name="hw_activation_need_warning_description">To complete setup, secure app access with Access Code.</string>
<string name="hw_activation_need_warning_description">Complete setup by securing the app with an access code.</string>
<string name="hw_backup_alert_description">If you do, you\'ll need to start over.</string>
<string name="hw_backup_alert_title">Are you sure you want to exit the activation process?</string>
<string name="hw_backup_alert_title">Are you sure you want to quit the activation process?</string>
<string name="hw_backup_close_description">If you do, you\'ll need to start over.</string>
<string name="hw_backup_google_drive_description">Recover an existing wallet stored in your Google Drive backup</string>
<string name="hw_backup_google_drive_title">Google Drive Backup</string>
<string name="hw_backup_hardware_description">Upgrade your security right away with a best in class hardware wallet from Tangem.</string>
<string name="hw_backup_google_drive_description">Recover existing wallet via Google Drive backup</string>
<string name="hw_backup_google_drive_title">Google Drive backup</string>
<string name="hw_backup_hardware_description">Level up your security with a superior Tangem hardware wallet.</string>
<string name="hw_backup_hardware_title">Hardware Wallet</string>
<string name="hw_backup_need_action">Go to backup</string>
<string name="hw_backup_need_description">To secure your wallet with a Access Code, complete the backup first.</string>
@ -538,22 +538,22 @@
<string name="hw_create_title">Create Mobile Wallet</string>
<string name="hw_import_seed_phrase_already_imported">This recovery phrase has already been imported</string>
<string name="hw_mobile_wallet">Mobile Wallet</string>
<string name="hw_upgrade_error_card_already_has_wallet">This device cant be used for upgrade, it already contains another wallet.</string>
<string name="hw_upgrade_error_card_key_import">Choose another device, this one cant be used for upgrade.</string>
<string name="hw_upgrade_error_card_already_has_wallet">Cant upgrade. A wallet already exists on this device</string>
<string name="hw_upgrade_error_card_key_import">Pick another device. This one cant be used for the upgrade.</string>
<string name="hw_upgrade_error_wallet2_card_required">An error occurred during the operation.</string>
<string name="hw_upgrade_funds_access_description">Your funds stay safe and fully accessible during the process</string>
<string name="hw_upgrade_funds_access_title">Funds access</string>
<string name="hw_upgrade_general_security_description">All private wallet data will be removed from the mobile app and stored securely on your Tangem device only</string>
<string name="hw_upgrade_general_security_description">Your wallet data will be erased from the app and stored on your Tangem device</string>
<string name="hw_upgrade_general_security_title">General Security</string>
<string name="hw_upgrade_key_migration_description">Private keys will be moved from the app to your Tangem card or ring</string>
<string name="hw_upgrade_key_migration_description">Private keys will be moved from the app to your Tangem device</string>
<string name="hw_upgrade_key_migration_title">Key Migration</string>
<string name="hw_upgrade_scan_device">Scan device</string>
<string name="hw_upgrade_start_action">Start upgrade</string>
<string name="hw_upgrade_start_description">Youre about to upgrade your wallet to Tangem Wallet. This will keep your assets safe with cold storage.</string>
<string name="hw_upgrade_start_description">Youre about to upgrade to a Tangem device, where your assets stay safe in cold storage.</string>
<string name="hw_upgrade_start_title">Tangem Wallet</string>
<string name="hw_upgrade_title">Upgrade to Hardware Wallet</string>
<string name="hw_upgrade_to_cold_banner_description">Keep your crypto safe with Tangems best-in-class hardware wallet.</string>
<string name="hw_upgrade_to_cold_banner_title">Upgrade wallet with a hardware backup</string>
<string name="hw_upgrade_to_cold_banner_description">Keep your crypto safe with Tangem\'s top-tier hardware wallet.</string>
<string name="hw_upgrade_to_cold_banner_title">Upgrade your wallet to hardware storage</string>
<string name="information_generated_with_ai">This information was generated with AI.\nTap here, if you find any errors.</string>
<string name="initial_message_change_access_code_body">To change the access code tap the card or ring as shown above and do not remove until the end of the operation</string>
<string name="initial_message_change_passcode_body">To change the passcode tap the card as shown above and do not remove until the end of the operation</string>
@ -759,8 +759,8 @@
<string name="notification_referral_promo_text">Share your code - earn 5 USDT per sale. Your friend gets 10% OFF.</string>
<string name="notification_referral_promo_title">Get REWARDS for every friend!</string>
<string name="notification_sepa_button">Buy crypto</string>
<string name="notification_sepa_text">Enjoy zero fees when purchasing crypto via SEPA transfer.</string>
<string name="notification_sepa_title">Buy Crypto with SEPA</string>
<string name="notification_sepa_text">Tangem slashes SEPA fees to almost nothing, giving you the best deal yet.</string>
<string name="notification_sepa_title">Buy crypto and don\'t pay fees!</string>
<string name="onboarding_access_code_feature_1_description">Set up a single access code to protect all your devices.</string>
<string name="onboarding_access_code_feature_1_title">Protect</string>
<string name="onboarding_access_code_feature_2_description">Set an individual access code for each card or ring later.</string>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -261,7 +261,7 @@ internal class DefaultOnrampRepository(
storeOnrampPairs(pairs = onrampPairs.await(), providers = providers.await())
}
override suspend fun hasMercuryoSepaMethod(
override suspend fun hasSepaMethod(
userWallet: UserWallet,
currency: OnrampCurrency,
country: OnrampCountry,
@ -278,7 +278,7 @@ internal class DefaultOnrampRepository(
appPreferencesStore = appPreferencesStore,
),
body = OnrampPairsRequest(
fromCurrencyCode = currency.code,
fromCurrencyCode = EUR_CURRENCY_CODE,
countryCode = country.code,
to = listOf(
OnrampDestinationDTO(
@ -599,5 +599,6 @@ internal class DefaultOnrampRepository(
const val REDIRECT_URL = "https://tangem.com/onramp"
const val SEPA_METHOD_ID = "sepa"
const val EUR_CURRENCY_CODE = "EUR"
}
}

View file

@ -13,7 +13,7 @@ class GetOnrampCountriesUseCase(
private val errorResolver: OnrampErrorResolver,
) {
suspend operator fun invoke(): EitherFlow<OnrampError, List<OnrampCountry>> {
operator fun invoke(): EitherFlow<OnrampError, List<OnrampCountry>> {
return onrampRepository.getCountries().map {
Either.catch { it }.mapLeft(errorResolver::resolve)
}

View file

@ -0,0 +1,19 @@
package com.tangem.domain.onramp
import arrow.core.Either
import com.tangem.domain.onramp.model.OnrampCurrency
import com.tangem.domain.onramp.model.error.OnrampError
import com.tangem.domain.onramp.repositories.OnrampErrorResolver
import com.tangem.domain.onramp.repositories.OnrampRepository
class OnrampGetDefaultCurrencyUseCase(
private val onrampRepository: OnrampRepository,
private val errorResolver: OnrampErrorResolver,
) {
suspend operator fun invoke(): Either<OnrampError, OnrampCurrency> {
return Either
.catch { requireNotNull(onrampRepository.getDefaultCurrencySync()) }
.mapLeft { errorResolver.resolve(it) }
}
}

View file

@ -23,7 +23,7 @@ class OnrampSepaAvailableUseCase(
}
return Either.catch {
repository.hasMercuryoSepaMethod(
repository.hasSepaMethod(
userWallet = userWallet,
currency = currency,
country = country,

View file

@ -15,7 +15,7 @@ interface OnrampRepository {
suspend fun getCountriesSync(): List<OnrampCountry>?
suspend fun getCountryByIp(userWallet: UserWallet): OnrampCountry
suspend fun getStatus(userWallet: UserWallet, txId: String): OnrampStatus
suspend fun hasMercuryoSepaMethod(
suspend fun hasSepaMethod(
userWallet: UserWallet,
currency: OnrampCurrency,
country: OnrampCountry,

View file

@ -2,18 +2,46 @@ package com.tangem.domain.promo
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.promo.models.PromoId
import com.tangem.domain.settings.repositories.SettingsRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import java.util.Calendar
class ShouldShowPromoWalletUseCase(private val promoRepository: PromoRepository) {
class ShouldShowPromoWalletUseCase(
private val promoRepository: PromoRepository,
private val settingsRepository: SettingsRepository,
) {
operator fun invoke(userWalletId: UserWalletId, promoId: PromoId): Flow<Boolean> {
return flow {
emit(false)
emitAll(promoRepository.isReadyToShowWalletPromo(userWalletId, promoId))
val promoFlow = promoRepository.isReadyToShowWalletPromo(userWalletId, promoId)
.map { applyWalletFirstUsageCondition(promoId, it) }
emitAll(promoFlow)
}
}
private suspend fun applyWalletFirstUsageCondition(promoId: PromoId, isReady: Boolean): Boolean {
if (!isReady) return false
return when (promoId) {
PromoId.Referral -> true
PromoId.Sepa -> {
val walletFirstUsageDate = settingsRepository.getWalletFirstUsageDate()
if (walletFirstUsageDate == 0L) return false
val currentDate = Calendar.getInstance().timeInMillis
currentDate - walletFirstUsageDate > ONE_DAY_IN_MILLIS
}
}
}
suspend fun neverToShow(promoId: PromoId) = promoRepository.setNeverToShowWalletPromo(promoId)
private companion object {
const val ONE_DAY_IN_MILLIS = 1 * 24 * 60 * 60 * 1000L
}
}

View file

@ -24,6 +24,7 @@ import com.tangem.domain.settings.usercountry.GetUserCountryUseCase
import com.tangem.domain.settings.usercountry.models.UserCountry
import com.tangem.domain.settings.usercountry.models.needApplyFCARestrictions
import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.onramp.model.OnrampCurrency
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.features.onramp.main.OnrampMainComponent
import com.tangem.features.onramp.main.entity.*
@ -55,6 +56,8 @@ internal class OnrampMainComponentModel @Inject constructor(
private val fetchQuotesUseCase: OnrampFetchQuotesUseCase,
private val getOnrampQuotesUseCase: GetOnrampQuotesUseCase,
private val fetchPairsUseCase: OnrampFetchPairsUseCase,
private val onrampSaveDefaultCurrencyUseCase: OnrampSaveDefaultCurrencyUseCase,
private val onrampGetDefaultCurrencyUseCase: OnrampGetDefaultCurrencyUseCase,
private val amountInputManager: InputManager,
private val messageSender: UiMessageSender,
private val urlOpener: UrlOpener,
@ -66,6 +69,7 @@ internal class OnrampMainComponentModel @Inject constructor(
private val params: OnrampMainComponent.Params = paramsContainer.require()
private var isSepaLaunched = false
private var currencyToRestore: OnrampCurrency? = null
val userWallet = getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId }
@ -100,6 +104,11 @@ internal class OnrampMainComponentModel @Inject constructor(
modelScope.launch {
clearOnrampCacheUseCase()
if (params.launchSepa) {
currencyToRestore = onrampGetDefaultCurrencyUseCase.invoke().getOrNull()
onrampSaveDefaultCurrencyUseCase.invoke(EUR_CURRENCY)
}
}
sendScreenOpenAnalytics()
@ -294,6 +303,13 @@ internal class OnrampMainComponentModel @Inject constructor(
override fun onDestroy() {
modelScope.launch { clearOnrampCacheUseCase.invoke() }
quotesTaskScheduler.cancelTask()
modelScope.launch {
if (params.launchSepa) {
currencyToRestore?.let { onrampSaveDefaultCurrencyUseCase.invoke(it) }
}
}
super.onDestroy()
}
@ -440,5 +456,13 @@ internal class OnrampMainComponentModel @Inject constructor(
const val UPDATE_DELAY = 10_000L
const val SEPA_METHOD_ID = "sepa"
val EUR_CURRENCY = OnrampCurrency(
code = "EUR",
name = "Euro",
unit = "",
precision = 2,
image = "https://s3.eu-central-1.amazonaws.com/tangem.api/express/Currencies/EUR.png",
)
}
}