diff --git a/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt index a0e87e1ab1..0c20fd0993 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/OnrampDomainModule.kt @@ -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( diff --git a/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt index e35089b9e9..76a87ca009 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/PromoDomainModule.kt @@ -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 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 60ebb679d5..ce2beab7d1 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -644,6 +644,8 @@ Присоединиться Поделись промокодом — заработай 5 USDT с каждой покупки. Твои друзья получат скидку 10% на карту Tangem! Получай бонусы за каждого друга! + Tangem снижает комиссии SEPA почти до нуля, предлагая вам лучшие условия. + Покупайте криптовалюту без комиссии! Установите единый код доступа для защиты всех ваших карт или колец Защита Установите индивидуальный код доступа для каждой карты или кольца позже. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index f2dc5313d9..7bf68cc60f 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -512,18 +512,18 @@ Do you want to allow “Tangem” to use biometric authentication? To confirm your identity and open the app to %s On %s network - Are you sure you want to exit the access code creation process? + Are you sure you want to cancel access code setup? Backup Now To complete setup, back up your wallet and secure app access with a Access Code. Finish Now Finish Wallet Activation - To complete setup, secure app access with Access Code. + Complete setup by securing the app with an access code. If you do, you\'ll need to start over. - Are you sure you want to exit the activation process? + Are you sure you want to quit the activation process? If you do, you\'ll need to start over. - Recover an existing wallet stored in your Google Drive backup - Google Drive Backup - Upgrade your security right away with a best in class hardware wallet from Tangem. + Recover existing wallet via Google Drive backup + Google Drive backup + Level up your security with a superior Tangem hardware wallet. Hardware Wallet Go to backup To secure your wallet with a Access Code, complete the backup first. @@ -538,22 +538,22 @@ Create Mobile Wallet This recovery phrase has already been imported Mobile Wallet - This device can’t be used for upgrade, it already contains another wallet. - Choose another device, this one can’t be used for upgrade. + Can’t upgrade. A wallet already exists on this device + Pick another device. This one can’t be used for the upgrade. An error occurred during the operation. Your funds stay safe and fully accessible during the process Funds access - All private wallet data will be removed from the mobile app and stored securely on your Tangem device only + Your wallet data will be erased from the app and stored on your Tangem device General Security - Private keys will be moved from the app to your Tangem card or ring + Private keys will be moved from the app to your Tangem device Key Migration Scan device Start upgrade - You’re about to upgrade your wallet to Tangem Wallet. This will keep your assets safe with cold storage. + You’re about to upgrade to a Tangem device, where your assets stay safe in cold storage. Tangem Wallet Upgrade to Hardware Wallet - Keep your crypto safe with Tangem’s best-in-class hardware wallet. - Upgrade wallet with a hardware backup + Keep your crypto safe with Tangem\'s top-tier hardware wallet. + Upgrade your wallet to hardware storage This information was generated with AI.\nTap here, if you find any errors. To change the access code tap the card or ring as shown above and do not remove until the end of the operation To change the passcode tap the card as shown above and do not remove until the end of the operation @@ -759,8 +759,8 @@ Share your code - earn 5 USDT per sale. Your friend gets 10% OFF. Get REWARDS for every friend! Buy crypto - Enjoy zero fees when purchasing crypto via SEPA transfer. - Buy Crypto with SEPA + Tangem slashes SEPA fees to almost nothing, giving you the best deal yet. + Buy crypto and don\'t pay fees! Set up a single access code to protect all your devices. Protect Set an individual access code for each card or ring later. diff --git a/core/ui/src/main/res/drawable/img_notification_sepa.webp b/core/ui/src/main/res/drawable/img_notification_sepa.webp index 3ca547ac85..f33044f9ec 100644 Binary files a/core/ui/src/main/res/drawable/img_notification_sepa.webp and b/core/ui/src/main/res/drawable/img_notification_sepa.webp differ diff --git a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt index 6d8b5311ce..ae8fe9d967 100644 --- a/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt +++ b/data/onramp/src/main/java/com/tangem/data/onramp/DefaultOnrampRepository.kt @@ -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" } } \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampCountriesUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampCountriesUseCase.kt index 1ede7cb75b..e57bfdfacd 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampCountriesUseCase.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/GetOnrampCountriesUseCase.kt @@ -13,7 +13,7 @@ class GetOnrampCountriesUseCase( private val errorResolver: OnrampErrorResolver, ) { - suspend operator fun invoke(): EitherFlow> { + operator fun invoke(): EitherFlow> { return onrampRepository.getCountries().map { Either.catch { it }.mapLeft(errorResolver::resolve) } diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampGetDefaultCurrencyUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampGetDefaultCurrencyUseCase.kt new file mode 100644 index 0000000000..4945eac2a7 --- /dev/null +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampGetDefaultCurrencyUseCase.kt @@ -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 { + return Either + .catch { requireNotNull(onrampRepository.getDefaultCurrencySync()) } + .mapLeft { errorResolver.resolve(it) } + } +} \ No newline at end of file diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt index fb43156695..ad7c22bfaa 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/OnrampSepaAvailableUseCase.kt @@ -23,7 +23,7 @@ class OnrampSepaAvailableUseCase( } return Either.catch { - repository.hasMercuryoSepaMethod( + repository.hasSepaMethod( userWallet = userWallet, currency = currency, country = country, diff --git a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt index 0a7ad02041..2dad8a9e87 100644 --- a/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt +++ b/domain/onramp/src/main/java/com/tangem/domain/onramp/repositories/OnrampRepository.kt @@ -15,7 +15,7 @@ interface OnrampRepository { suspend fun getCountriesSync(): List? 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, diff --git a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt index d3496cb02e..0fd7070d88 100644 --- a/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt +++ b/domain/promo/src/main/java/com/tangem/domain/promo/ShouldShowPromoWalletUseCase.kt @@ -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 { 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 + } } \ No newline at end of file diff --git a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt index 99c271c260..832304f55a 100644 --- a/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt +++ b/features/onramp/impl/src/main/kotlin/com/tangem/features/onramp/main/model/OnrampMainComponentModel.kt @@ -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", + ) } } \ No newline at end of file