diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 62ba2f5b49..7d37eacaf5 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -2,6 +2,7 @@ package com.tangem.tap import com.tangem.TangemSdkLogger import com.tangem.blockchainsdk.BlockchainSDKFactory +import com.tangem.blockchainsdk.signer.TransactionSignerFactory import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.filter.OneTimeEventFilter import com.tangem.core.featuretoggle.manager.FeatureTogglesManager @@ -113,6 +114,8 @@ interface ApplicationEntryPoint { fun getTangemAppLogger(): TangemAppLoggerInitializer + fun getTransactionSignerFactory(): TransactionSignerFactory + fun getHomeFeatureToggles(): HomeFeatureToggles fun getGetUserCountryCodeUseCase(): GetUserCountryUseCase diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index 073068f66c..0b5a37f14d 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -8,9 +8,15 @@ import com.tangem.Log import com.tangem.TangemSdkLogger import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.blockchainsdk.BlockchainSDKFactory +import com.tangem.blockchainsdk.signer.TransactionSignerFactory import com.tangem.common.routing.AppRouter import com.tangem.core.analytics.Analytics +import com.tangem.core.analytics.api.ParamsInterceptor import com.tangem.core.analytics.filter.OneTimeEventFilter +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic +import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm import com.tangem.core.featuretoggle.manager.FeatureTogglesManager import com.tangem.datasource.api.common.MoshiConverter import com.tangem.datasource.api.common.createNetworkLoggingInterceptor @@ -175,6 +181,9 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { private val tangemAppLoggerInitializer: TangemAppLoggerInitializer get() = entryPoint.getTangemAppLogger() + private val transactionSignerFactory: TransactionSignerFactory + get() = entryPoint.getTransactionSignerFactory() + private val homeFeatureToggles: HomeFeatureToggles get() = entryPoint.getHomeFeatureToggles() @@ -260,6 +269,7 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { urlOpener = urlOpener, shareManager = shareManager, appRouter = appRouter, + transactionSignerFactory = transactionSignerFactory, homeFeatureToggles = homeFeatureToggles, getUserCountryUseCase = getUserCountryUseCase, ), @@ -297,6 +307,25 @@ abstract class TangemApplication : Application(), ImageLoaderFactory { logConfig = LogConfig.analyticsHandlers, jsonConverter = MoshiConverter.sdkMoshiConverter, ) + + Analytics.addParamsInterceptor( + interceptor = object : ParamsInterceptor { + override fun id(): String = "SendTransactionSignerInfoInterceptor" + + override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.TransactionSent + + override fun intercept(params: MutableMap) { + val isLastSignWithRing = store.state.globalState.isLastSignWithRing + + params[AnalyticsParam.WALLET_FORM] = if (isLastSignWithRing) { + WalletForm.Ring.name + } else { + WalletForm.Card.name + } + } + }, + ) + factory.build(Analytics, buildData) // ExceptionHandler.append(blockchainExceptionHandler) TODO: [REDACTED_JIRA] } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt index e7c6feee04..edc221250e 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/paramsInterceptor/CardContextInterceptor.kt @@ -10,7 +10,11 @@ import com.tangem.tap.common.analytics.converters.ParamCardCurrencyConverter import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.analytics.events.MainScreen +import com.tangem.tap.common.extensions.inject import com.tangem.tap.features.demo.DemoHelper +import com.tangem.tap.proxy.redux.DaggerGraphState +import com.tangem.tap.store +import kotlinx.coroutines.runBlocking /** [REDACTED_AUTHOR] @@ -19,6 +23,8 @@ class CardContextInterceptor( private val scanResponse: ScanResponse, ) : ParamsInterceptor { + private val walletsRepository = store.inject(DaggerGraphState::walletsRepository) + private val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() override fun id(): String = CardContextInterceptor.id() @@ -33,7 +39,7 @@ class CardContextInterceptor( override fun intercept(params: MutableMap) { val card = scanResponse.card params[AnalyticsParam.BATCH] = card.batchId - params[AnalyticsParam.PRODUCT_TYPE] = getProductType(scanResponse) + params[AnalyticsParam.PRODUCT_TYPE] = getProductType() params[AnalyticsParam.FIRMWARE] = card.firmwareVersion.stringValue if (userWalletId != null) { params[AnalyticsParam.USER_WALLET_ID] = userWalletId.stringValue @@ -44,7 +50,13 @@ class CardContextInterceptor( } } - private fun getProductType(scanResponse: ScanResponse): String { + private fun getProductType(): String { + if (scanResponse.productType != ProductType.Ring && userWalletId != null) { + val isWalletWithRing = runBlocking { walletsRepository.isWalletWithRing(userWalletId) } + + if (isWalletWithRing) return "Ring" + } + return when (scanResponse.productType) { ProductType.Note -> "Note" ProductType.Twins -> "Twin" @@ -53,18 +65,18 @@ class CardContextInterceptor( ProductType.Ring -> "Ring" ProductType.Start2Coin -> "Start2Coin" ProductType.Visa -> "VISA" - else -> if (DemoHelper.isDemoCard(scanResponse)) { - if (DemoHelper.isTestDemoCard(scanResponse)) { - "Demo Test" - } else { - when (scanResponse.card.cardId.substring(0..1)) { - "AC" -> "Demo Wallet" - "AB" -> "Demo Note" - else -> "Demo Other" - } - } - } else { - "Other" + else -> if (DemoHelper.isDemoCard(scanResponse)) getDemoCardProductType() else "Other" + } + } + + private fun getDemoCardProductType(): String { + return if (DemoHelper.isTestDemoCard(scanResponse)) { + "Demo Test" + } else { + when (scanResponse.card.cardId.substring(0..1)) { + "AC" -> "Demo Wallet" + "AB" -> "Demo Note" + else -> "Demo Other" } } } diff --git a/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt new file mode 100644 index 0000000000..edd0ded835 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt @@ -0,0 +1,22 @@ +package com.tangem.tap.common.libs.blockchainsdk + +import com.tangem.Message +import com.tangem.TangemSdk +import com.tangem.blockchain.common.TransactionSigner +import com.tangem.blockchainsdk.signer.TransactionSignerFactory +import com.tangem.tap.common.redux.global.GlobalAction +import com.tangem.tap.domain.TangemSigner +import com.tangem.tap.store + +internal class DefaultTransactionSignerFactory : TransactionSignerFactory { + + override fun createTransactionSigner(cardId: String?, sdk: TangemSdk): TransactionSigner { + return TangemSigner( + cardId = cardId, + tangemSdk = sdk, + initialMessage = Message(), + ) { signResponse -> + store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt index 6e64597093..a9525dc46c 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalAction.kt @@ -72,6 +72,8 @@ sealed class GlobalAction : Action { val walletPublicKey: ByteArray, ) : GlobalAction() + data class IsSignWithRing(val isSignWithRing: Boolean) : GlobalAction() + data class SetConfigManager(val environmentConfigStorage: EnvironmentConfigStorage) : GlobalAction() object ExchangeManager : GlobalAction() { diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt index 223296f720..6884603331 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalReducer.kt @@ -68,6 +68,7 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde ) globalState.copy(scanResponse = globalState.scanResponse.copy(card = newCardInstance)) } + is GlobalAction.IsSignWithRing -> globalState.copy(isLastSignWithRing = action.isSignWithRing) is GlobalAction.ShowDialog -> { globalState.copy(dialog = action.stateDialog) } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt index 054469bc26..0317eaaca6 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalState.kt @@ -24,6 +24,7 @@ data class GlobalState( @Deprecated("Use GetUserCountryCodeUseCase instead") val userCountryCode: String? = null, val appThemeMode: AppThemeMode = AppThemeMode.DEFAULT, + val isLastSignWithRing: Boolean = false, ) : StateType typealias CryptoCurrencyName = String diff --git a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt index e175d51e25..51ed0f3dd5 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt @@ -125,6 +125,14 @@ internal object SettingsDomainModule { return ShouldShowSwapPromoWalletUseCase(promoSettingsRepository) } + @Provides + @Singleton + fun provideShouldShowRingPromoUseCase( + promoSettingsRepository: PromoSettingsRepository, + ): ShouldShowRingPromoUseCase { + return ShouldShowRingPromoUseCase(promoSettingsRepository) + } + @Provides @Singleton fun provideShouldShowTravalaPromoWalletUseCase( diff --git a/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt new file mode 100644 index 0000000000..36bc5ce13a --- /dev/null +++ b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt @@ -0,0 +1,23 @@ +package com.tangem.tap.di.libs.blockchainsdk + +import com.tangem.blockchainsdk.signer.TransactionSignerFactory +import com.tangem.tap.common.libs.blockchainsdk.DefaultTransactionSignerFactory +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +/** +[REDACTED_AUTHOR] + */ +@Module +@InstallIn(SingletonComponent::class) +internal class TransactionSignerFactoryModule { + + @Provides + @Singleton + fun provideTransactionSignerFactory(): TransactionSignerFactory { + return DefaultTransactionSignerFactory() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt index f316b2e433..f53d9d0736 100644 --- a/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt +++ b/app/src/main/java/com/tangem/tap/domain/TangemSigner.kt @@ -5,17 +5,15 @@ import com.tangem.TangemSdk import com.tangem.blockchain.common.TransactionSigner import com.tangem.blockchain.common.Wallet import com.tangem.common.CompletionResult -import com.tangem.domain.common.TapWorkarounds.isTangemTwins -import com.tangem.domain.models.scan.CardDTO +import com.tangem.domain.models.scan.isRing import com.tangem.tap.domain.tasks.SignHashesTask import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.resume class TangemSigner( - private val card: CardDTO, + private val cardId: String?, private val tangemSdk: TangemSdk, private val initialMessage: Message, - private val accessCode: String? = null, private val signerCallback: (TangemSignerResponse) -> Unit, ) : TransactionSigner { @@ -24,21 +22,20 @@ class TangemSigner( publicKey: Wallet.PublicKey, ): CompletionResult> { return suspendCancellableCoroutine { continuation -> - val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins val task = SignHashesTask(hashes, publicKey) tangemSdk.startSessionWithRunnable( runnable = task, - cardId = card.cardId.takeIf { isCardNotBackedUp }, + cardId = cardId, initialMessage = initialMessage, - accessCode = accessCode, ) { result -> when (result) { is CompletionResult.Success -> { signerCallback( TangemSignerResponse( - result.data.totalSignedHashes, - result.data.remainingSignatures, + totalSignedHashes = result.data.totalSignedHashes, + remainingSignatures = result.data.remainingSignatures, + isRing = result.data.batchId?.let(::isRing) ?: false, ), ) if (continuation.isActive) { @@ -70,4 +67,5 @@ class TangemSigner( data class TangemSignerResponse( val totalSignedHashes: Int?, val remainingSignatures: Int?, + val isRing: Boolean, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/TangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/sdk/TangemSdkManager.kt index 5ee23082e0..49bef8a287 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/TangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/TangemSdkManager.kt @@ -137,5 +137,9 @@ interface TangemSdkManager { initialMessage: Message, ): CompletionResult + fun changeProductType(isRing: Boolean) + + fun clearProductType() + // endregion } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt index 8f9e869f0d..12c23b6fec 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/impl/DefaultTangemSdkManager.kt @@ -9,7 +9,6 @@ import com.tangem.TangemSdk import com.tangem.common.* import com.tangem.common.authentication.AuthenticationManager import com.tangem.common.authentication.keystore.KeystoreManager -import com.tangem.common.card.FirmwareVersion import com.tangem.common.core.* import com.tangem.common.extensions.ByteArrayKey import com.tangem.common.services.secure.SecureStorage @@ -138,6 +137,14 @@ class DefaultTangemSdkManager( scanResponse: ScanResponse, shouldReset: Boolean, ): CompletionResult { + tangemSdk.config.setupForProduct( + if (scanResponse.cardTypesResolver.isRing()) { + ProductType.RING + } else { + ProductType.CARD + }, + ) + return runTaskAsync( runnable = CreateProductWalletTask( cardTypesResolver = scanResponse.cardTypesResolver, @@ -145,10 +152,15 @@ class DefaultTangemSdkManager( shouldReset = shouldReset, ), cardId = scanResponse.card.cardId, - initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)), + initialMessage = if (scanResponse.cardTypesResolver.isRing()) { + Message(resources.getString(R.string.initial_message_create_wallet_body_ring)) + } else { + Message(resources.getString(R.string.initial_message_create_wallet_body)) + }, iconScanRes = if (scanResponse.cardTypesResolver.isRing()) R.drawable.img_hand_scan_ring else null, preflightReadFilter = null, ) + .doOnResult { tangemSdk.config.setupForProduct(ProductType.ANY) } } override suspend fun importWallet( @@ -162,6 +174,15 @@ class DefaultTangemSdkManager( } catch (e: TangemSdkError.MnemonicException) { return CompletionResult.Failure(e) } + + tangemSdk.config.setupForProduct( + if (scanResponse.cardTypesResolver.isRing()) { + ProductType.RING + } else { + ProductType.CARD + }, + ) + return runTaskAsync( runnable = CreateProductWalletTask( cardTypesResolver = scanResponse.cardTypesResolver, @@ -171,9 +192,14 @@ class DefaultTangemSdkManager( shouldReset = shouldReset, ), cardId = scanResponse.card.cardId, - initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)), + initialMessage = if (scanResponse.cardTypesResolver.isRing()) { + Message(resources.getString(R.string.initial_message_create_wallet_body_ring)) + } else { + Message(resources.getString(R.string.initial_message_create_wallet_body)) + }, preflightReadFilter = null, ) + .doOnResult { tangemSdk.config.setupForProduct(ProductType.ANY) } } private fun sendScanResultsToAnalytics(result: CompletionResult) { @@ -404,6 +430,16 @@ class DefaultTangemSdkManager( return runTaskAsync(runnable = task, cardId = null, initialMessage = initialMessage, preflightReadFilter = null) } + override fun changeProductType(isRing: Boolean) { + tangemSdk.config.setupForProduct( + type = if (isRing) ProductType.RING else ProductType.CARD, + ) + } + + override fun clearProductType() { + tangemSdk.config.setupForProduct(type = ProductType.ANY) + } + override suspend fun finalizeTwin( secondCardPublicKey: ByteArray, issuerKeyPair: KeyPair, @@ -422,18 +458,5 @@ class DefaultTangemSdkManager( companion object { private const val MAX_INITIALIZE_ATTEMPTS = 10 - - @Deprecated("Use [DefaultCardSdkProvider] instead") - val config = Config( - linkedTerminal = true, - allowUntrustedCards = true, - filter = CardFilter( - allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(), - maxFirmwareVersion = FirmwareVersion(major = 6, minor = 33), - batchIdFilter = CardFilter.Companion.ItemFilter.Deny( - items = setOf("0027", "0030", "0031", "0035"), - ), - ), - ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/sdk/impl/MockTangemSdkManager.kt b/app/src/main/java/com/tangem/tap/domain/sdk/impl/MockTangemSdkManager.kt index bddbaad9d6..faad2661c4 100644 --- a/app/src/main/java/com/tangem/tap/domain/sdk/impl/MockTangemSdkManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/sdk/impl/MockTangemSdkManager.kt @@ -177,6 +177,10 @@ class MockTangemSdkManager( return MockProvider.createSecondTwinWallet() } + override fun changeProductType(isRing: Boolean) = Unit + + override fun clearProductType() = Unit + override suspend fun finalizeTwin( secondCardPublicKey: ByteArray, issuerKeyPair: KeyPair, diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt index 3a8a5bd48c..e5616aacd7 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/SignHashesTask.kt @@ -12,6 +12,7 @@ class TangemSignHashesResponse( val signatures: List, val totalSignedHashes: Int?, val remainingSignatures: Int?, + val batchId: String?, ) : CommandResponse class SignHashesTask( @@ -22,12 +23,14 @@ class SignHashesTask( SignHashesCommand(hashes.toTypedArray(), publicKey.seedKey, publicKey.derivationPath).run(session) { response -> when (response) { is CompletionResult.Success -> { + val card = session.environment.card callback( CompletionResult.Success( TangemSignHashesResponse( - response.data.signatures, - response.data.totalSignedHashes, - session.environment.card?.wallet(publicKey.seedKey)?.remainingSignatures, + signatures = response.data.signatures, + totalSignedHashes = response.data.totalSignedHashes, + remainingSignatures = card?.wallet(publicKey.seedKey)?.remainingSignatures, + batchId = card?.batchId, ), ), ) diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt index d72eb92e23..2fcfc2411a 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/product/ScanProductTask.kt @@ -24,6 +24,7 @@ import com.tangem.domain.common.configs.CardConfig import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_IDS +import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_PREFIX import com.tangem.domain.models.scan.ProductType import com.tangem.domain.models.scan.ScanResponse import com.tangem.operations.ScanTask @@ -248,7 +249,7 @@ private class ScanWalletProcessor( } private fun getWalletProductType(card: CardDTO): ProductType { - if (RING_BATCH_IDS.contains(card.batchId)) { + if (RING_BATCH_IDS.contains(card.batchId) || card.batchId.startsWith(RING_BATCH_PREFIX)) { return ProductType.Ring } return if (card.firmwareVersion >= FirmwareVersion.Ed25519Slip0010Available && diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 0ee7f0e2ea..17fb4389ab 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -211,11 +211,13 @@ class WalletConnectSdkHelper { } private suspend fun sendTransaction(data: WcTransactionData, cardId: String?): String? { + val sdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk + val result = (data.walletManager as TransactionSender).send( transactionData = data.transaction, - signer = CommonSigner( - tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk, + signer = store.inject(DaggerGraphState::transactionSignerFactory).createTransactionSigner( cardId = cardId, + sdk = sdk, ), ) return when (result) { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 64ce8d1864..e7cc9589a4 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -3,6 +3,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux import android.net.Uri import com.tangem.common.CompletionResult import com.tangem.domain.wallets.models.UserWalletId +import com.tangem.common.card.Card import com.tangem.feature.onboarding.data.model.CreateWalletResponse import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource import com.tangem.tap.domain.tasks.product.CreateProductWalletTaskResponse @@ -62,6 +63,7 @@ sealed class BackupAction : Action { data object ErrorInBackupCard : BackupAction() data object StartAddingPrimaryCard : BackupAction() data object ScanPrimaryCard : BackupAction() + data class SetHasRing(val hasRing: Boolean) : BackupAction() /** * Check for unfinished backup of standard Wallets @@ -71,7 +73,7 @@ sealed class BackupAction : Action { data object StartAddingBackupCards : BackupAction() data object AddBackupCard : BackupAction() { - data object Success : BackupAction() + data class Success(val card: Card) : BackupAction() data class ChangeButtonLoading(val isLoading: Boolean) : BackupAction() } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index 73afe9b5d4..d77bf753a1 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -15,9 +15,12 @@ import com.tangem.domain.common.extensions.withIOContext import com.tangem.domain.common.extensions.withMainContext import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.models.scan.CardDTO +import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_IDS +import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_PREFIX import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.wallets.builder.UserWalletBuilder import com.tangem.domain.wallets.legacy.UserWalletsListManager +import com.tangem.domain.wallets.builder.UserWalletIdBuilder import com.tangem.domain.wallets.models.Artwork import com.tangem.domain.wallets.models.UserWallet import com.tangem.feature.onboarding.data.model.CreateWalletResponse @@ -172,11 +175,14 @@ private fun handleWalletAction(action: Action) { BackupService.State.FinalizingPrimaryCard -> BackupAction.PrepareToWritePrimaryCard is BackupService.State.FinalizingBackupCard -> BackupAction.PrepareToWriteBackupCard(backupState.index) else -> { - if (onboardingWalletState.backupState.backupStep == BackupStep.InitBackup || + if (onboardingWalletState.backupState.backupStep == null || + onboardingWalletState.backupState.backupStep == BackupStep.InitBackup || onboardingWalletState.backupState.backupStep == BackupStep.Finished ) { Analytics.send(Onboarding.Backup.ScreenOpened()) - BackupAction.IntroduceBackup + + val isWallet2 = scanResponse?.cardTypesResolver?.isWallet2() ?: false + if (isWallet2) BackupAction.StartBackup else BackupAction.IntroduceBackup } else { null } @@ -192,6 +198,14 @@ private fun handleWalletAction(action: Action) { private fun handleFinishBackup(scanResponse: ScanResponse) { val backupState = store.state.onboardingWalletState.backupState val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) + + val userWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build() + if (backupState.hasRing && userWalletId != null) { + scope.launch { + store.inject(DaggerGraphState::walletsRepository).setHasWalletsWithRing(userWalletId = userWalletId) + } + } + OnboardingHelper.saveWallet( scanResponse = updatedScanResponse, accessCode = backupState.accessCode, @@ -445,7 +459,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) when (result) { is CompletionResult.Success -> { updateArtworks(backupService.addedBackupCardsCount, result.data) - store.dispatchOnMain(BackupAction.AddBackupCard.Success) + store.dispatchOnMain(BackupAction.AddBackupCard.Success(result.data)) } is CompletionResult.Failure -> { val crashlytics = FirebaseCrashlytics.getInstance() @@ -499,11 +513,12 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } } is BackupAction.WritePrimaryCard -> { - val iconScanRes = if (scanResponse?.cardTypesResolver?.isRing() == true) { - R.drawable.img_hand_scan_ring - } else { - null - } + val isRing = scanResponse?.cardTypesResolver?.isRing() == true + val iconScanRes = if (isRing) R.drawable.img_hand_scan_ring else null + + store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing)) + + tangemSdkManager.changeProductType(isRing) backupService.proceedBackup(iconScanRes = iconScanRes) { result -> when (result) { is CompletionResult.Success -> { @@ -511,10 +526,19 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } is CompletionResult.Failure -> Unit } + tangemSdkManager.clearProductType() } } is BackupAction.WriteBackupCard -> { - backupService.proceedBackup { result -> + val cardIndex = if (action.cardNumber > 0) action.cardNumber - 1 else action.cardNumber + val backupCard = backupState.backupCards.getOrNull(cardIndex) + val isRing = backupCard.isRing() + val iconScanRes = if (isRing) R.drawable.img_hand_scan_ring else null + + store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing)) + + tangemSdkManager.changeProductType(isRing) + backupService.proceedBackup(iconScanRes = iconScanRes) { result -> when (result) { is CompletionResult.Success -> { val backupValidator = BackupValidator() @@ -539,6 +563,8 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } } } + + tangemSdkManager.clearProductType() } } is BackupAction.DiscardBackup -> { @@ -652,6 +678,10 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) } } +private fun Card?.isRing(): Boolean { + return this?.let { RING_BATCH_IDS.contains(batchId) || batchId.startsWith(RING_BATCH_PREFIX) } ?: false +} + private suspend fun saveWallet( userWalletsListManager: UserWalletsListManager, userWallet: UserWallet, @@ -724,7 +754,7 @@ internal fun gatherCardIds(backupState: BackupState, card: CardDTO?): List { showInterruptOnboardingDialog() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 0b0fe48d88..d34a661c97 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.onboarding.products.wallet.redux -import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.redux.OnboardingManageTokensAction import com.tangem.tap.backupService import com.tangem.tap.common.redux.AppState @@ -75,7 +74,6 @@ private object ReducerForGlobalAction { canSkipBackup = action.canSkipBackup, startedSource = action.source, ), - isRingOnboarding = action.scanResponse.cardTypesResolver.isRing(), ) } is GlobalAction.Onboarding.StartForUnfinishedBackup -> { @@ -104,7 +102,7 @@ private object OnboardingWallet2Reducer { } private object BackupReducer { - @Suppress("ComplexMethod") + @Suppress("ComplexMethod", "LongMethod") fun reduce(action: BackupAction, state: BackupState): BackupState { return when (action) { is BackupAction.IntroduceBackup -> BackupState( @@ -113,9 +111,26 @@ private object BackupReducer { canSkipBackup = state.canSkipBackup, startedSource = state.startedSource, ) - BackupAction.StartAddingPrimaryCard -> state.copy(backupStep = BackupStep.ScanOriginCard) - BackupAction.StartAddingBackupCards -> state.copy(backupStep = BackupStep.AddBackupCards) - BackupAction.AddBackupCard.Success -> state.copy(backupCardsNumber = state.backupCardsNumber + 1) + BackupAction.StartAddingPrimaryCard -> { + state.copy( + backupStep = BackupStep.ScanOriginCard, + maxBackupCards = 2, + canSkipBackup = state.canSkipBackup, + ) + } + BackupAction.StartAddingBackupCards -> { + state.copy( + backupStep = BackupStep.AddBackupCards, + maxBackupCards = 2, + canSkipBackup = state.canSkipBackup, + ) + } + is BackupAction.AddBackupCard.Success -> { + state.copy( + backupCards = state.backupCards + action.card, + backupCardsNumber = state.backupCardsNumber + 1, + ) + } is BackupAction.AddBackupCard.ChangeButtonLoading -> state.copy(showBtnLoading = action.isLoading) BackupAction.ShowAccessCodeInfoScreen -> state.copy(backupStep = BackupStep.SetAccessCode) BackupAction.ShowEnterAccessCodeScreen -> state.copy( @@ -130,7 +145,9 @@ private object BackupReducer { is BackupAction.PrepareToWritePrimaryCard -> if (state.primaryCardId == null) { state.copy( primaryCardId = backupService.primaryCardId, + primaryCardBatchId = backupService.primaryCardBatchId, backupCardIds = backupService.backupCardIds, + backupCardBatchIds = backupService.backupCardsBatchIds, backupCardsNumber = backupService.backupCardIds.size, backupStep = BackupStep.WritePrimaryCard, ) @@ -140,7 +157,9 @@ private object BackupReducer { is BackupAction.PrepareToWriteBackupCard -> if (state.primaryCardId == null) { state.copy( primaryCardId = backupService.primaryCardId, + primaryCardBatchId = backupService.primaryCardBatchId, backupCardIds = backupService.backupCardIds, + backupCardBatchIds = backupService.backupCardsBatchIds, backupCardsNumber = backupService.backupCardIds.size, backupStep = BackupStep.WriteBackupCard(action.cardNumber), ) @@ -152,6 +171,14 @@ private object BackupReducer { is BackupAction.FinishBackup -> state.copy(backupStep = BackupStep.Finished) BackupAction.OnAccessCodeDialogClosed -> state.copy(backupStep = BackupStep.AddBackupCards) BackupAction.DiscardBackup -> BackupState() + is BackupAction.SetHasRing -> { + // Don't update if state.has ring is already true + if (state.hasRing) { + state + } else { + state.copy(hasRing = action.hasRing) + } + } else -> state } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index 2ff57b4881..af1af41924 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -2,6 +2,7 @@ package com.tangem.tap.features.onboarding.products.wallet.redux import android.graphics.Bitmap import android.net.Uri +import com.tangem.common.card.Card import com.tangem.domain.redux.StateDialog import com.tangem.domain.wallets.models.UserWalletId import org.rekotlin.StateType @@ -31,6 +32,7 @@ data class OnboardingWalletState( OnboardingWalletStep.CreateWallet, OnboardingWalletStep.None -> 1 OnboardingWalletStep.Backup -> { when (backupState.backupStep) { + null -> 2 BackupStep.InitBackup -> 2 BackupStep.ScanOriginCard -> 3 BackupStep.AddBackupCards -> 4 @@ -67,19 +69,23 @@ enum class OnboardingWalletStep { data class BackupState( val primaryCardId: String? = null, + val primaryCardBatchId: String? = null, val backupCardsNumber: Int = 0, + val backupCards: List = emptyList(), val backupCardIds: List = emptyList(), + val backupCardBatchIds: List = emptyList(), @Transient val backupCardsArtworks: Map = emptyMap(), val accessCode: String = "", val accessCodeError: AccessCodeError? = null, - val backupStep: BackupStep = BackupStep.InitBackup, + val backupStep: BackupStep? = null, val maxBackupCards: Int = 2, val canSkipBackup: Boolean = true, val isInterruptedBackup: Boolean = false, val showBtnLoading: Boolean = false, val hasBackupError: Boolean = false, val startedSource: BackupStartedSource = BackupStartedSource.Onboarding, + val hasRing: Boolean = false, ) enum class BackupStartedSource { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt index a755b8e1d1..74277c326f 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/ui/OnboardingWalletFragment.kt @@ -42,6 +42,7 @@ import com.tangem.core.ui.windowsize.rememberWindowSize import com.tangem.datasource.utils.isNullOrEmpty import com.tangem.domain.common.util.cardTypesResolver import com.tangem.domain.feedback.models.FeedbackEmailType +import com.tangem.domain.models.scan.isRing import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.onboarding.data.model.CreateWalletResponse import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource @@ -223,6 +224,9 @@ class OnboardingWalletFragment : when { state.wallet2State != null -> { seedPhraseStateHandler.newState(this, state, seedPhraseViewModel) + seedPhraseViewModel.setCardArtworkUri( + cardArtworkUri = state.walletImages.primaryCardImage.toString(), + ) updateWalletImagesState(state.walletImages) } else -> { @@ -324,6 +328,7 @@ class OnboardingWalletFragment : private fun setBackupState(state: BackupState) { when (state.backupStep) { + null -> Unit BackupStep.InitBackup -> showBackupIntro(state) BackupStep.ScanOriginCard -> showScanOriginCard() BackupStep.AddBackupCards -> showAddBackupCards(state) @@ -477,13 +482,26 @@ class OnboardingWalletFragment : reInitCardsWidgetIfNeeded(state.backupCardsNumber) prepareViewForFinalizeStep() - val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) - tvHeader.text = getText(R.string.common_origin_card) - tvBody.text = getString( - R.string.onboarding_subtitle_scan_primary_card_format, - state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) }, + val isRing = state.primaryCardBatchId != null && isRing(batchId = state.primaryCardBatchId) + + tvHeader.text = getText( + if (isRing) R.string.common_origin_ring else R.string.common_origin_card, ) - layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_backup_origin) + + tvBody.text = if (isRing) { + getString(R.string.onboarding_subtitle_scan_ring) + } else { + val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) + getString( + R.string.onboarding_subtitle_scan_primary_card_format, + state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) }, + ) + } + + layoutButtonsCommon.btnWalletMainAction.text = getText( + if (isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin, + ) + layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24) layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WritePrimaryCard) } @@ -507,16 +525,26 @@ class OnboardingWalletFragment : prepareViewForFinalizeStep() val cardNumber = (state.backupStep as? BackupStep.WriteBackupCard)?.cardNumber ?: 1 - val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) - tvHeader.text = getString(R.string.onboarding_title_backup_card_format, cardNumber) - tvBody.text = getString( - R.string.onboarding_subtitle_scan_backup_card_format, - cardIdFormatter.getFormattedCardId(state.backupCardIds[cardNumber - 1]), + + val isRing = isRing(batchId = state.backupCardBatchIds[cardNumber - 1]) + tvHeader.text = getString( + if (isRing) R.string.onboarding_title_backup_ring else R.string.onboarding_title_backup_card, ) + + tvBody.text = if (isRing) { + getString(R.string.onboarding_subtitle_scan_ring) + } else { + val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4)) + getString( + R.string.onboarding_subtitle_scan_backup_card_format, + state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) }, + ) + } + layoutButtonsCommon.btnWalletMainAction.text = getString( - R.string.onboarding_button_backup_card_format, - cardNumber, + if (isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin, ) + layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24) layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WriteBackupCard(cardNumber)) diff --git a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt index 99ddfe6b5b..7331b9f95c 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/DefaultExpressAuthProvider.kt @@ -1,12 +1,17 @@ package com.tangem.tap.network.auth +import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.PreferencesKeys +import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.lib.auth.ExpressAuthProvider +import kotlinx.coroutines.runBlocking import java.util.UUID import java.util.concurrent.atomic.AtomicReference internal class DefaultExpressAuthProvider( private val userWalletsStore: UserWalletsStore, + private val appPreferencesStore: AppPreferencesStore, ) : ExpressAuthProvider { private var uuid = AtomicReference(UUID.randomUUID()) @@ -18,4 +23,18 @@ internal class DefaultExpressAuthProvider( override fun getSessionId(): String { return uuid.get().toString() } + + override fun getRefCode(): String { + val addedWalletsWithRings = runBlocking { + appPreferencesStore.getSyncOrDefault( + key = PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY, + default = emptySet(), + ) + } + + val userWalletId = userWalletsStore.selectedUserWalletOrNull?.walletId?.stringValue + ?: error("No user id provided") + + return if (addedWalletsWithRings.contains(userWalletId)) "ring" else "" + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt index 54d0fdbc78..12e5639c12 100644 --- a/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt +++ b/app/src/main/java/com/tangem/tap/network/auth/di/AuthModule.kt @@ -2,6 +2,7 @@ package com.tangem.tap.network.auth.di import com.tangem.datasource.api.common.AuthProvider import com.tangem.datasource.local.config.environment.EnvironmentConfigStorage +import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.lib.auth.ExpressAuthProvider import com.tangem.lib.auth.StakeKitAuthProvider @@ -29,8 +30,14 @@ class AuthModule { @Provides @Singleton - fun provideExpressAuthProvider(userWalletsStore: UserWalletsStore): ExpressAuthProvider { - return DefaultExpressAuthProvider(userWalletsStore = userWalletsStore) + fun provideExpressAuthProvider( + userWalletsStore: UserWalletsStore, + appPreferencesStore: AppPreferencesStore, + ): ExpressAuthProvider { + return DefaultExpressAuthProvider( + userWalletsStore = userWalletsStore, + appPreferencesStore = appPreferencesStore, + ) } @Provides diff --git a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt index fb01befe82..2008fae3cc 100644 --- a/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt +++ b/app/src/main/java/com/tangem/tap/network/exchangeServices/CurrencyExchangeManager.kt @@ -7,6 +7,7 @@ import com.tangem.blockchain.common.AmountType import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.blockchain.extensions.Result +import com.tangem.domain.common.TapWorkarounds.isTangemTwins import com.tangem.domain.models.scan.CardDTO import com.tangem.domain.models.scan.ScanResponse import com.tangem.domain.tokens.model.CryptoCurrency @@ -105,8 +106,9 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa val coinValue = walletManager.wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO if (coinValue < fee.amount.value) return + val isCardNotBackedUp = card.backupStatus?.isActive != true && !card.isTangemTwins val signer = TangemSigner( - card = card, + cardId = card.cardId.takeIf { isCardNotBackedUp }, tangemSdk = store.inject(DaggerGraphState::cardSdkConfigRepository).sdk, initialMessage = Message(), ) { signResponse -> @@ -117,6 +119,8 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa remainingSignatures = signResponse.remainingSignatures, ), ) + + store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing)) } walletManager.send( diff --git a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt index 674924336e..56c13b9a41 100644 --- a/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt +++ b/app/src/main/java/com/tangem/tap/proxy/redux/DaggerGraphState.kt @@ -2,6 +2,7 @@ package com.tangem.tap.proxy.redux import com.tangem.TangemSdkLogger import com.tangem.blockchainsdk.BlockchainSDKFactory +import com.tangem.blockchainsdk.signer.TransactionSignerFactory import com.tangem.common.routing.AppRouter import com.tangem.core.navigation.email.EmailSender import com.tangem.core.navigation.share.ShareManager @@ -83,6 +84,7 @@ data class DaggerGraphState( val shareManager: ShareManager? = null, val appRouter: AppRouter? = null, val pushNotificationsRouter: PushNotificationsRouter? = null, + val transactionSignerFactory: TransactionSignerFactory? = null, val homeFeatureToggles: HomeFeatureToggles? = null, val getUserCountryUseCase: GetUserCountryUseCase? = null, ) : StateType \ No newline at end of file diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt index 5fc6c4e12c..94637867c0 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt @@ -170,6 +170,7 @@ sealed class AnalyticsParam { const val BATCH = "Batch" const val TYPE = "Type" const val FEE_TYPE = "Fee Type" + const val WALLET_FORM = "WalletForm" const val PERMISSION_TYPE = "Permission Type" const val PRODUCT_TYPE = "Product Type" const val FIRMWARE = "Firmware" diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/Basic.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/Basic.kt index 6fb52dfe29..3c1d48f13b 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/Basic.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/Basic.kt @@ -67,6 +67,10 @@ sealed class Basic( enum class MemoType { Empty, Full, Null } + + enum class WalletForm { + Card, Ring + } } class ScanError(error: Throwable) : Basic( diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/SwitchEnvironmentInterceptor.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/SwitchEnvironmentInterceptor.kt index dbfbc5e54f..e47f1f8494 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/SwitchEnvironmentInterceptor.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/SwitchEnvironmentInterceptor.kt @@ -46,7 +46,9 @@ internal class SwitchEnvironmentInterceptor( private fun Request.Builder.addHeaders(headers: Map>): Request.Builder { headers.forEach { (name, valueProvider) -> - addHeader(name = name, value = valueProvider()) + val value = valueProvider() + + if (value.isNotBlank()) addHeader(name = name, value = value) } return this diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt index 2442807b3c..2be7c447f4 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/common/config/Express.kt @@ -51,6 +51,7 @@ internal class Express( put(key = "user-id", value = Provider(expressAuthProvider::getUserId)) put(key = "session-id", value = Provider(expressAuthProvider::getSessionId)) putAll(from = RequestHeader.AppVersionPlatformHeaders(appVersionProvider).values) + put(key = "refcode", value = Provider(expressAuthProvider::getRefCode)) } private fun getApiKey(isProd: Boolean): String { diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index d2c600c572..10f76c5e66 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -99,18 +99,15 @@ object PreferencesKeys { val apiConfigsEnvironmentKey by lazy { stringPreferencesKey(name = "apiConfigsEnvironment") } + val ADDED_WALLETS_WITH_RING_KEY by lazy { stringSetPreferencesKey(name = "addedWalletsWithRing") } + + val SHOULD_SHOW_RING_PROMO_KEY by lazy { booleanPreferencesKey(name = "shouldShowRingPromo") } + // region Permission fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission") fun getShouldShowInitialPermissionScreen(permission: String) = booleanPreferencesKey("shouldShowInitialPushPermissionScreen_$permission") - - fun getIsFirstTimeAskingPermission(permission: String) = - booleanPreferencesKey("shouldAskInitialPushPermission_$permission") - - fun getPermissionLaunchCount(permission: String) = intPreferencesKey("pushPermissionLaunchCount_$permission") - - fun getPermissionDaysCount(permission: String) = longPreferencesKey("pushPermissionDaysCount_$permission") // endregion fun getUserTokensKey(userWalletId: String) = stringPreferencesKey(name = "user_tokens_$userWalletId") diff --git a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt index 3bd2cd29e2..02ade46775 100644 --- a/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt +++ b/core/datasource/src/test/kotlin/com/tangem/datasource/api/common/config/managers/ProdApiConfigsManagerTest.kt @@ -44,6 +44,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) { every { appVersionProvider.versionName } returns VERSION_NAME every { expressAuthProvider.getUserId() } returns EXPRESS_USER_ID every { expressAuthProvider.getSessionId() } returns EXPRESS_SESSION_ID + every { expressAuthProvider.getRefCode() } returns EXPRESS_REF_CODE every { stakeKitAuthProvider.getApiKey() } returns STAKE_KIT_API_KEY } @@ -65,6 +66,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) { const val VERSION_NAME = "debug" const val EXPRESS_USER_ID = "express_user_id" const val EXPRESS_SESSION_ID = "express_session_id" + const val EXPRESS_REF_CODE = "express_ref_code" const val STAKE_KIT_API_KEY = "stake_kit_api_key" @JvmStatic @@ -113,6 +115,7 @@ internal class ProdApiConfigsManagerTest(private val model: Model) { }, "user-id" to Provider { EXPRESS_USER_ID }, "session-id" to Provider { EXPRESS_SESSION_ID }, + "refcode" to Provider { EXPRESS_REF_CODE }, "version" to Provider { VERSION_NAME }, "platform" to Provider { "android" }, ), diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index 242e76cf07..dff794c63c 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -12,19 +12,19 @@ Transaktion kann nicht gesendet werden Das gewählte unterstützt nicht das %1$s Netzwerk Um die kryptografische Verschlüsselung der %1$s Blockchain zu aktivieren, musst Du die Wallet auf die Werkseinstellungen zurücksetzen. Bitte heb vorher dein Guthaben ab, um sicherzustellen, dass du nichts verlierst, und führe dann den Reset-Vorgang durch. Nach dem Zurücksetzen ist der Zugriff auf die aktuelle Wallet nicht mehr möglich. - Tokens im %1$s -Netzwerk werden von dieser Karte aufgrund einer Firmware-Einschränkung nicht unterstützt. - Hast du Probleme beim Scannen deiner Karte? - Diese Karte ist für die Zusammenarbeit mit Tangem nicht geeignet + Tokens im %1$s -Netzwerk werden von dieser Karte oder Ring aufgrund einer Firmware-Einschränkung nicht unterstützt. + Hast du Probleme beim Scannen deiner Karte oder Ring? + Diese Karte oder Ring ist für die Zusammenarbeit mit Tangem nicht geeignet Standardgebühr Aktiviere die Option Standardgebühr, um die Transaktionsgebühren automatisch festzulegen und die Gebührenseite beim Senden von Geldern zu überspringen. Du kannst bei Bedarf jederzeit zu dieser Seite zurückkehren. Gehe zu den Einstellungen, um die biometrische Authentifizierung in der Tangem-App zu aktivieren Biometrische Authentifizierung aktivieren Dadurch werden alle gespeicherten Zugangscodes für die Wallet gelöscht. Jede weitere Operation mit der Wallet erfordert die Übermittlung des Zugangscodes. - Durch das Entfernen der gespeicherten Karte werden alle gespeicherten Wallets und deren Zugangscodes aus der App gelöscht. + Durch das Entfernen der gespeicherten Karte oder Ring werden alle gespeicherten Wallets und deren Zugangscodes aus der App gelöscht. Zugangscode speichern - Bei Interaktionen mit deiner Karte wird anstelle des Zugangscodes eine biometrische Authentifizierung abgefragt. + Bei Interaktionen mit deiner Karte oder Ring wird anstelle des Zugangscodes eine biometrische Authentifizierung abgefragt. Behalte die Wallet in der App - Aktiviere die Verknüpfung aller Wallets mit der Tangem-App. Die biometrische Authentifizierung ist zum Entsperren der App erforderlich. Das Signieren von Transaktionen erfordert das Antippen deiner Tangem-Karte. + Aktiviere die Verknüpfung aller Wallets mit der Tangem-App. Die biometrische Authentifizierung ist zum Entsperren der App erforderlich. Das Signieren von Transaktionen erfordert das Antippen deiner Tangem-Karte oder Ring. Dunkel Hell Systemstandard @@ -34,29 +34,29 @@ Nicht mehr anzeigen Verstanden Guthaben sind ausgeblendet - Bitte Karte scannen + Bitte Karte oder Ring scannen Bitte versuche es in 30 Sekunden erneut oder scanne die Karte Zu viele Versuche Du hast die biometrische Authentifizierung auf deinem Telefon deaktiviert und kannst keine Wallets in der App speichern. Um Wallets zu speichern, aktiviere bitte die biometrische Authentifizierung in deinen Telefoneinstellungen. Backup-Prozess starten Verwende eine Bankkarte oder eine andere Zahlungsmethode - %d Karte - %d Karten + %d Karte oder Ring + %d Karten oder Ringe - Deaktiviere diese Option, wenn du nicht möchtest, dass diese Karte zum Zurücksetzen von Zugangscodes auf anderen Karten in dieser Wallets verwendet wird. Bitte beachte, dass du dann auch den Zugangscode auf dieser Karte nicht zurücksetzen kannst. - Ermöglicht die Verwendung dieser Karte zum Zurücksetzen des Zugangscodes auf anderen Karten in dieser Brieftasche + Deaktiviere diese Option, wenn du nicht möchtest, dass diese Karte oder Ring zum Zurücksetzen von Zugangscodes auf anderen Karten oder Ringe in dieser Wallets verwendet wird. Bitte beachte, dass du dann auch den Zugangscode auf dieser Karte oder Ring nicht zurücksetzen kannst. + Ermöglicht die Verwendung dieser Karte oder Ring zum Zurücksetzen des Zugangscodes auf anderen Karten oder Ringe in dieser Brieftasche Zugangspin resetten Zurücksetzen Möchtest du das wirklich tun? Zugangscode ändern - Der Zugangscode wird nur auf dieser Karte geändert - Alle Karten der ausgewählten Wallet wurden auf die Werkseinstellungen zurückgesetzt. Du kannst nun eine neue Wallet aufsetzen. + Der Zugangscode wird nur auf dieser Karte oder Ring geändert + Alle Karten oder Ringe der ausgewählten Wallet wurden auf die Werkseinstellungen zurückgesetzt. Du kannst nun eine neue Wallet aufsetzen. Komplett zurücksetzen - Möchtest du die nächste Karte in dieser Wallet zurücksetzen? - Karte zurücksetzen - Wir empfehlen dir, den Zurücksetzungsprozess für alle Karten in dieser Wallet abzuschließen - Du hast nicht alle deine Karten zurückgesetzt + Möchtest du die nächste Karte oder Ring in dieser Wallet zurücksetzen? + Karte oder Ring zurücksetzen + Wir empfehlen dir, den Zurücksetzungsprozess für alle Karten oder Ringe in dieser Wallet abzuschließen + Du hast nicht alle deine Karten oder Ringe zurückgesetzt Auf Werkseinstellungen zurücksetzen Sicherheitsmodus Karteneinstellungen @@ -134,7 +134,7 @@ Keine Adresse Jetzt OK - Hauptkarte + Hauptkarte oder Ring Primärring Passphrase Einfügen @@ -211,17 +211,17 @@ Kaufe eine Tangem Wallet Chat Zugangscode - Du musst den richtigen Zugangscode eingeben, bevor du die Karte scannst. + Du musst den richtigen Zugangscode eingeben, bevor du die Karte oder Ring scannst. Langes Tippen - Dieser Mechanismus schützt vor Annäherungsangriffen auf eine Karte. Es wird eine Verzögerung zwischen dem Empfang und der Ausführung eines Befehls erzwungen. Nach der ersten signierten Transaktion wird dieses Telefon mit der Karte verknüpft und die Transaktionen werden sofort signiert + Dieser Mechanismus schützt vor Annäherungsangriffen auf eine Karte oder Ring. Es wird eine Verzögerung zwischen dem Empfang und der Ausführung eines Befehls erzwungen. Nach der ersten signierten Transaktion wird dieses Telefon mit der Karte oder Ring verknüpft und die Transaktionen werden sofort signiert Passcode Bevor du einen Befehl ausführst, der eine Änderung des Kartenstatus zur Folge hat, musst du den Passcode eingeben. Empfehlungsprogramm Flippe den Bildschirm deines Geräts nach unten, um Salden schnell ein- und auszublenden %s Hasch - KartenID + Karten- oder Ring-ID Kontakt zum Support - Weitere Karten verknüpfen + Weitere Karten oder Ringe verknüpfen App Währung Flipp um Guthaben auszublenden Aussteller @@ -230,7 +230,7 @@ Details Überprüfe deine Internetverbindung oder wechseln zu einem anderen Netzwerk Nutzungsbedingungen - Du hast eine Karte aus einer anderen Wallet verwendet. Tippe auf die Karte, die dieser Wallet zugeordnet ist. + Du hast eine Karte oder Ring aus einer anderen Wallet verwendet. Tippe auf die Karte oder Ring, die dieser Wallet zugeordnet ist. Meine Token Du hast noch keine Token hinzugefügt. Füge Token über den Markt zum Tausch hinzu Kann nicht gegen %s ausgetauscht werden @@ -287,11 +287,11 @@ Tauschen jeden Vermögenswert in Deinem Portfolio gegen diesen Token Die folgenden Angaben sind freiwillig. Du kannst diese löschen, wenn du sie nicht weitergeben möchtest. Teile uns mit, welche Funktionen du vermisst, und wir werden versuchen, dir zu helfen. - Bitte sag uns, welche Karte du hast + Bitte sag uns, welche Karte oder Ring du hast Hallo Support-Team, Bitte erzähle uns mehr über dein Problem. Jedes kleine Detail kann helfen. Meine Vorschläge - Kann eine Karte nicht scannen + Kann eine Karte oder Ring nicht scannen Rückmeldung Feedback zu Tangem Eine Transaktion kann nicht gesendet werden @@ -305,18 +305,18 @@ Um fortzufahren, erteile %1s Smart Contracts die Berechtigung, dein zu %2s verwenden. Erlaubnis erteilen Unbegrenzt - Karte bestellen - Karte scannen + Karte oder Ring bestellen + Karte oder Ring scannen Diese Information ist KI generiert - Um den Zugangscode zu ändern, halte die Karte wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. - Um den Passcode zu ändern, halte die Karte wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. - Um die Wallet zu erstellen, halte die Karte wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. + Um den Zugangscode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. + Um den Passcode zu ändern, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. + Um die Wallet zu erstellen, halte die Karte oder Ring wie oben gezeigt an das Gerät und entferne sie erst am Ende des Vorgangs. Um die Wallet zu erstellen, tippe auf den Ring wie oben gezeigt und entferne ihn erst am Ende des Vorgangs - Halte deine Karte Nr. %s des Sets an dein Smartphone - Legen Sie die Karte zum Scannen an + Halte deine Karte oder Ring Nr. %s des Sets an dein Smartphone + Legen Sie die Karte oder Ring zum Scannen an Tippen um zu signieren - Lege die Karte an - Du hast deine biometrischen Daten aktualisiert, scanne deine Karte, um einzutreten + Lege die Karte oder Ring an + Du hast deine biometrischen Daten aktualisiert, scanne deine Karte oder Ring, um einzutreten Dein Guthaben sollte höher sein als der Gebührenwert, um eine Überweisung zu tätigen Unzureichende Mittel Du hast nicht genug Mana für diese Transaktion. Bitte warte, bis das Mana wieder aufgefüllt ist. Dein Mana-Guthaben beträgt %1$s/%2$s @@ -327,8 +327,8 @@ Mana-Level Um mit der Verfolgung deiner Krypto-Assets und -Transaktionen zu beginnen, füge einen Token hinzu Token verwalten - Um auf alle Netzwerke zugreifen zu können, musst du die Karte scannen - Scanne deine Karte + Um auf alle Netzwerke zugreifen zu können, musst du die Karte oder Ring scannen + Scanne deine Karte oder Ring Genießen %1$s Servicegebühren auf Swaps über Changelly von Februar %2$s-%3$s Swap mit Changelly, %s Gebühren Token @@ -362,7 +362,7 @@ Verfügbare Netzwerke Mein Portfolio Markt - Um Adressen für ausgewählte Netzwerke zu generieren, musst du eine Tangem-Karte scannen + Um Adressen für ausgewählte Netzwerke zu generieren, musst du eine Tangem-Karte oder Ring scannen Um Token hinzuzufügen, rufe dies auf oder tippe auf die Suchleiste Die Daten dieses Abschnitts stammen aus den folgenden Netzwerken: %s Die Daten konnten nicht geladen werden... @@ -455,11 +455,11 @@ Rufe dies auf oder tippe auf die Suchleiste, um Token direkt vom Markt hinzuzufügen Token hinzufügen NFC ist auf deinem Gerät nicht verfügbar - Du musst einen einzigen Zugangscode einrichten, um alle deine Karten zu schützen + Du musst einen einzigen Zugangscode einrichten, um alle deine Karten oder Ringe zu schützen Schützen - Du kannst später auf jeder Karte einen individuellen Zugangscode einrichten + Du kannst später auf jeder Karte oder Ring einen individuellen Zugangscode einrichten Personalisieren - Der Zugangscode kann mit einer verbundenen Karte wiederhergestellt werden. Bewahre nicht alle Karten an einem Ort auf. + Der Zugangscode kann mit einer verbundenen Karte oder Ring wiederhergestellt werden. Bewahre nicht alle Karten oder Ringe an einem Ort auf. Wiederherstellen Wähle ein beliebiges Wort, eine Phrase oder eine Zahl als Zugangscode Zugangscode erstellen @@ -467,36 +467,36 @@ Gebe deinen Zugangscode erneut ein Der Zugangscode muss mindestens 4 Zeichen lang sein Der eingegebene Zugangscode stimmt nicht mit dem ursprünglichen Zugangscode überein - Bitte wiederhole den Vorgang. Die Karte wird auf Werkseinstellungen zurückgesetzt. + Bitte wiederhole den Vorgang. Die Karte oder Ring wird auf Werkseinstellungen zurückgesetzt. Aktivierungsfehler Token hinzufügen - Du hast eine Backup-Karte hinzugefügt. Wenn der Backup-Prozess abgeschlossen ist, kannst du keine weiteren Backup-Karten hinzufügen. Wenn du noch eine Karte hast, füge diese zum Backup hinzu. Möchtest du den Backup-Prozess fortsetzen? + Du hast eine Backup-Karte oder Ring hinzugefügt. Wenn der Backup-Prozess abgeschlossen ist, kannst du keine weiteren Backup-Karten oder Ringe hinzufügen. Wenn du noch eine Karte oder Ring hast, füge diese zum Backup hinzu. Möchtest du den Backup-Prozess fortsetzen? Der Sicherungsvorgang ist teilweise abgeschlossen. Du kannst ihn jetzt nicht beenden. Die Passphrase ist eine fortschrittliche Sicherheitsfunktion, die von Krypto-Wallets verwendet wird. Sie fügt ein zusätzliches Wort oder eine Phrase deiner Wahl zu der bereits bestehenden Wiederherstellungsphrase hinzu, um einen brandneuen Satz von Adressen zu erzeugen. - Hinzufügen einer Sicherungskarte - Karte scannen - Scanne die Karte Nr. %d + Hinzufügen einer Sicherungskarte oder Ring + Karte oder Ring scannen + Scanne die Karte oder Ring Nr. %d Jetzt sichern - Scannen der Hauptkarte + Scannen der Hauptkarte oder Ring Ring scannen Weiter zu meiner Wallet Backup abschließen Krypto empfangen - Primärkarte scannen + Primärkarte oder Ring scannen Für später überspringen Wie funktioniert es? - Lass uns alle Schlüssel auf deiner Karte generieren und eine sichere Wallet erstellen + Lass uns alle Schlüssel auf deiner Karte oder Ring generieren und eine sichere Wallet erstellen Ein Wallet erstellen Erstelle eine Wallet Andere Optionen - Deine Schlüssel(private-keys) werden sicher im Inneren der Karte generiert. Es gibt keine Seed-Phrase, d. h. niemand kann sie exportieren oder stehlen. + Deine Schlüssel(private-keys) werden sicher im Inneren der Karte oder Ring generiert. Es gibt keine Seed-Phrase, d. h. niemand kann sie exportieren oder stehlen. Schlüssel anonym generieren - Deine Karte ist aktiviert und einsatzbereit + Deine Karte oder Ring ist aktiviert und einsatzbereit Erfolgreich! In diesem Fall musst du ganz von vorne anfangen. Möchtest du den Aktivierungsprozess abbrechen? Erste Schritte - Für die Karte, die du hinzufügen möchtest, wurde bereits eine andere Wallets erstellt. Wenn du Guthaben auf dieser Wallets hast, hebe es bitte ab, setze diese Karte zurück und füge sie als Backup hinzu. + Für die Karte oder Ring, die du hinzufügen möchtest, wurde bereits eine andere Wallets erstellt. Wenn du Guthaben auf dieser Wallets hast, hebe es bitte ab, setze diese Karte oder Ring zurück und füge sie als Backup hinzu. Backups anlegen Lese mehr über die Seed-Phrase @@ -511,27 +511,30 @@ Um deine Wallets zu importieren, gib bitte deine Seed-Phrase in das folgende Feld ein Seed-Phrase generieren Wallet importieren - Eine Seed-Phrase ist eine Reihe von Wörtern, mit denen du deine Wallet wiederherstellen kannst. Im Gegensatz zu den von der Karte generierten Schlüsseln sind Seed-Phrasen ungeschützt und können kopiert und gestohlen werden. Die Verwendung dieser Option erfolgt auf eigene Gefahr. + Eine Seed-Phrase ist eine Reihe von Wörtern, mit denen du deine Wallet wiederherstellen kannst. Im Gegensatz zu den von der Karte oder Ring generierten Schlüsseln sind Seed-Phrasen ungeschützt und können kopiert und gestohlen werden. Die Verwendung dieser Option erfolgt auf eigene Gefahr. Seed-Phrase verwenden Ungültige Seed-Phrase. Bitte überprüfe die Wortreihenfolge. Ungültige Seed-Phrase. Bitte überprüfe die Rechtschreibung. Veralteter Standard Um zu überprüfen, ob du deine Seed-Phrase richtig aufgeschrieben hast, gib bitte das 2., 7. und 11 Wort ein. Eine letzte Prüfung! - Um den Sicherungsvorgang zu starten, füge bis zu zwei Sicherungskarten hinzu. - Du kannst eine weitere Karte hinzufügen oder den Sicherungsvorgang abschließen - Bereite die Sicherungskarte mit der Nummer %s vor. - Scanne die primär-Karte, um den Sicherungsvorgang zu starten. - Bereite die primäre Karte mit der Nummer %s vor. - Deine Tangem-Karte ist konfiguriert und einsatzbereit. - Maximale Anzahl an Karten hinzugefügt. Schließe den Sicherungsvorgang ab. - Karte aktivieren - Sicherungskarte Nr. %d - Keine Sicherungskarten + Um den Sicherungsvorgang zu starten, füge bis zu zwei Sicherungskarten oder Ring hinzu. + Du kannst eine weitere Karte oder Ring hinzufügen oder den Sicherungsvorgang abschließen + Bereite die Sicherungskarte oder Ring mit der Nummer %s vor. + Scanne die primär-Karte oder Ring, um den Sicherungsvorgang zu starten. + Bereite die primäre Karte oder Ring mit der Nummer %s vor. + Bereite den Ring vor und drücke unten die Scan-Taste + Deine Tangem-Karte oder Ring ist konfiguriert und einsatzbereit. + Maximale Anzahl an Karten oder Ringe hinzugefügt. Schließe den Sicherungsvorgang ab. + Karte oder Ring aktivieren + Sicherungs-Karte oder Ring + Sicherungskarte oder Ring Nr. %d + Sicherungs-Ring + Keine Sicherungskarten oder Sicherungsring Benachrichtigungen - Eine Backup-Karte hinzugefügt - Bereite deine Karte vor - Zwei Backup-Karten hinzugefügt + Eine Backup-Karte oder Ring hinzugefügt + Bereite deine Karte oder Ring vor + Zwei Backup-Karten oder Ring hinzugefügt Um zu beginnen, lade einfach die wallet mit einem beliebigen Betrag auf Um zu beginnen, lade die Wallet einfach mit mehr als %1$s %2$s auf. Krypto kaufen @@ -539,13 +542,13 @@ Aktivieren einer Wallet Der Twinning-Prozess ist teilweise abgeschlossen. Du kannst ihn jetzt nicht mehr beenden. Wenn der Prozess der Erstellung der Brieftasche in irgendeiner Weise unterbrochen wird, musst du diesen von vorne beginnen - Du kannst deine Schlüssel mit bis zu zwei weiteren leeren Tangem Wallet-Karten sichern. - Der Zugangscode kann mit einer der Ersatzkarten wiederhergestellt werden. - Alle Backup-Karten können als voll funktionsfähig mit den gleichen Schlüsseln verwendet werden. + Du kannst deine Schlüssel mit bis zu zwei weiteren leeren Tangem Wallet-Karten oder Ringe sichern. + Der Zugangscode kann mit einer der Ersatzkarten oder Ringe wiederhergestellt werden. + Alle Backup-Karten oder Ringe können als voll funktionsfähig mit den gleichen Schlüsseln verwendet werden. Du kannst einen Zugangscode zum Schutz deiner wallet festlegen. Wiederherstellungs-Wallet Zugangscode wiederherstellen - Identische Karten + Identische Karten oder Ring Zugangscode Gruppe erstellen Nach Guthaben @@ -587,16 +590,16 @@ %d Wallet %d Wallets - Karte zurücksetzen + Karte oder Ring zurücksetzen Mir ist bewusst, dass ich nach der Durchführung dieser Aktion keinen Zugriff mehr auf die aktuelle Wallet habe. - Mir ist klar, dass ich diese Karte nicht verwenden kann, um meinen Zugangscode auf den anderen Karten der aktuellen Wallet wiederherzustellen - Durch das Zurücksetzen auf Werkseinstellungen wird die Wallet vollständig von der ausgewählten Karte gelöscht. Du kannst die aktuelle Wallet nicht wiederherstellen oder die Karte verwenden, um den Zugangscode wiederherzustellen. - Beim Zurücksetzen auf die Werkseinstellungen wird die Wallet der ausgewählten Karte vollständig gelöscht und aus der App entfernt. Es ist nicht möglich, die aktuelle Wallet wiederherzustellen. + Mir ist klar, dass ich diese Karte oder Ring nicht verwenden kann, um meinen Zugangscode auf den anderen Karten oder Ringe der aktuellen Wallet wiederherzustellen + Durch das Zurücksetzen auf Werkseinstellungen wird die Wallet vollständig von der ausgewählten Karte oder Ring gelöscht. Du kannst die aktuelle Wallet nicht wiederherstellen oder die Karte oder Ring verwenden, um den Zugangscode wiederherzustellen. + Beim Zurücksetzen auf die Werkseinstellungen wird die Wallet der ausgewählten Karte oder Ring vollständig gelöscht und aus der App entfernt. Es ist nicht möglich, die aktuelle Wallet wiederherzustellen. Ringbesitzer erhalten bis zum 15.11. 3 provisionsfreie Swaps auf Changelly! Jetzt mit 0 %% Gebühren tauschen! Besitzt du eine Bankkarte aus einem anderen Land und eine Aufenthaltserlaubnis oder Registrierung außerhalb der Russischen Föderation? Russische Bankkarten werden derzeit nicht akzeptiert - Melde dich bei der App an und überprüfe dein Guthaben, ohne die Karte zu scannen + Melde dich bei der App an und überprüfe dein Guthaben, ohne die Karte oder Ring zu scannen Zugriff auf die App Nutzung biometrischer Daten zulassen Bei Interaktionen mit deiner Wallet werden anstelle des Zugangscodes biometrische Daten abgefragt @@ -604,9 +607,9 @@ Es sieht so aus, als ob du die biometrische Authentifizierung deaktiviert hast. Diese ist notwendig, um Wallets zu speichern Biometrische Autorisierung aktivieren Möchtest du Biometrie nutzen? - Beachte, dass für Transaktionen mit deinem Guthaben weiterhin deine Karte erforderlich ist - Karte scannen - Scanne die Karte, um ihre Einstellungen zu ändern. Die Änderungen wirken sich nur auf die von dir gescannte Karte aus und haben keine Auswirkungen auf andere mit deiner Wallet verknüpften Karten. + Beachte, dass für Transaktionen mit deinem Guthaben weiterhin deine Karte oder Ring erforderlich ist + Karte oder Ring scannen + Scanne die Karte oder Ring, um ihre Einstellungen zu ändern. Die Änderungen wirken sich nur auf die von dir gescannte Karte oder Ring aus und haben keine Auswirkungen auf andere mit deiner Wallet verknüpften Karten oder Ringe. Halte deine Karte bereit! Bereits in der eingegebenen Adresse enthalten Der Provisionsbetrag ist %s mal der empfohlene Betrag. Stelle sicher, dass die benutzerdefinierten Einstellungen korrekt sind. @@ -683,7 +686,7 @@ Die Transaktion wurde erfolgreich signiert und an den Blockchain-Knoten gesendet. Die Walletbilanz wird aktualisiert %1$s ist ein Vermögenswert im Tron-Netzwerk. Um die Gebühr zu berechnen und eine Transaktion durchzuführen, musst du etwas Tron (TRX) auf deinem Konto einzahlen. Transaktion gesendet - Bereite das Scannen der Karte vor, die du einrichten möchtest. + Bereite das Scannen der Karte oder Ring vor, die du einrichten möchtest. Entferne diese Wallet Hiermit wird die Wallet aus der Anwendung entfernt. Die Wallet selbst kann wieder hinzugefügt werden. Name @@ -779,13 +782,13 @@ Abstimmung Zurückziehen Deine Einsätze - Bewahre deine Krypto-Assets sicher auf, während die privaten Schlüssel auf deiner Karte bleiben + Bewahre deine Krypto-Assets sicher auf, während die privaten Schlüssel auf deiner Karte oder Ring bleiben Revolutionäre Hardware-Wallet - Bis zu 3 physische Karten pro Wallet + Bis zu 3 physische Karten oder Ringe pro Wallet Ultrasicheres Backup - Eine Hardware-Wallet für deine Bitcoins, Ethereum und viele weitere Währungen gleichzeitig – alles auf einer Karte + Eine Hardware-Wallet für deine Bitcoins, Ethereum und viele weitere Währungen gleichzeitig – alles auf einer Karte oder Ring Tausende von Währungen - Verwende es unterwegs, überall und jederzeit. Keine Kabel oder Batterien. Tippe einfach mit der Karte auf dein Telefon, wenn du Kryptowährung benötigst. + Verwende es unterwegs, überall und jederzeit. Keine Kabel oder Batterien. Tippe einfach mit der Karte oder Ring auf dein Telefon, wenn du Kryptowährung benötigst. Die Wallet für jeden Lerne Tangem kennen Tausche, kaufen Sie NFTs, vergebe Kredite und tätige Einlagen bei mehr als 100 verschiedenen dezentralen Diensten @@ -842,24 +845,24 @@ zu: %s Validierer: %s Versuche es erneut - Du hast dieselbe Karte gescannt. Um ein Zwillings-Wallet zu erstellen, musst du die Karte mit der Nummer %d scannen. - Du hast die falsche Doppelkarte gescannt. Bitte versuche eine andere Karte - Die, die du in den Hand hältst, und die andere mit der Nummer %s.\n\nBeide Karten können verwendet werden, um Geld aus dieser Wallet zu versenden. - Eine Wallet. Zwei Karten. - Scanne die Karte Nr. %s + Du hast dieselbe Karte oder Ring gescannt. Um ein Zwillings-Wallet zu erstellen, musst du die Karte oder Ring mit der Nummer %d scannen. + Du hast die falsche Doppelkarte oder Ring gescannt. Bitte versuche eine andere Karte oder Ring + Die, die du in den Hand hältst, und die andere mit der Nummer %s.\n\nBeide Karten oder Ringe können verwendet werden, um Geld aus dieser Wallet zu versenden. + Eine Wallet. Zwei Karten oder Ringe. + Scanne die Karte oder Ring Nr. %s Wallet erstellen - Scanne die Nr. %s Zwillingskarte - Karte vorbereiten + Scanne die Nr. %s Zwillingskarte oder Ring + Karte oder Ring vorbereiten Tangem Twin Diese Aktion ist unumkehrbar. Du hast keinen Zugriff mehr auf die alte Wallet. - Tippe auf die Doppelkarte mit der Nummer %s und entferne sie erst am Ende des Vorgangs. - Verwende %s oder scanne eine Karte, um Zugriff auf deine Wallet zu erhalten. + Tippe auf die Doppelkarte oder Ring mit der Nummer %s und entferne sie erst am Ende des Vorgangs. + Verwende %s oder scanne eine Karte oder Ring, um Zugriff auf deine Wallet zu erhalten. Bleib auf dem Laufenden mit den neuesten Funktionen und Neuigkeiten Sei der Erste, der von neuen Aktionen erfährt Möchtest du Push-Benachrichtigungen verwenden? Neues Wallet hinzufügen Möchtest du diese Wallet wirklich löschen? - Es ist ein Fehler aufgetreten, bitte scanne deine Karte, um sich anzumelden + Es ist ein Fehler aufgetreten, bitte scanne deine Karte oder Ring, um sich anzumelden Dieses Wallet wurde bereits gespeichert, du kannst ein weiteres hinzufügen Die Wallet mit dem Namen %s existiert bereits Wallet-Name @@ -867,7 +870,7 @@ Alle freischalten Alle mit %s freischalten Blockchain ist nicht erreichbar. Versuche es später nochmal - Karte scannen + Karte oder Ring scannen Aufforderung zum Signieren einer Nachricht. \n\n %s Dapp %1$s, mit der Bitte um\nBNB-Transaktion zu unterzeichnen.\n\n%2$s Handelsauftrag für %1$s\n Preis: %2$s\n Zu erhaltender Betrag: %3$s\n Zu zahlender Betrag: %4$s @@ -881,7 +884,7 @@ Sitzungsanfrage enthält nicht unterstützte Blockchains für WalletConnect-Verbindung. Nicht unterstützte Blockchains:\n Aufgrund der technischen Implementierung kann keine Verbindung zu dieser Dapp hergestellt werden. Es ist ein unbekannter Fehler aufgetreten. Fehlermeldung: %s. Wenn das Problem weiterhin besteht, wende dich bitte an unseren Support - Falsche Karte in der Tangem App ausgewählt + Falsche Karte oder Ring in der Tangem App ausgewählt Transaktion aus Dapp-Daten konnte nicht erstellt werden. Code: %s Es ist ein unbekannter Fehler aufgetreten. Fehlercode: %d. Wenn das Problem weiterhin besteht, wende dich bitte an unseren Support Keine geöffneten WalletConnect-Sitzungen @@ -892,7 +895,7 @@ Anfrage zum Starten einer Sitzung für\n %1$s\n\n NETZWERK: %2$s \n\n URL: %3$s Der Vorgang konnte nicht abgeschlossen werden. \n\nDu hast bereits eine WalletConnect-Sitzung mit diesen Parametern hergestellt. Neuen Code scannen - Mit dieser Karte kann keine WalletConnect-Sitzung hergestellt werden + Mit dieser Karte oder Ring kann keine WalletConnect-Sitzung hergestellt werden Dieses Netzwerk wird nicht unterstützt. Bitte wähle ein anderes Netzwerk. Netzwerk auswählen WalletConnect-Sitzungen @@ -906,10 +909,10 @@ Keine Internetverbindung Wallet-Einstellungen Tangem - Verwende %s oder scanne eine Karte, um den Zugriff auf deine Wallet freizuschalten. + Verwende %s oder scanne eine Karte oder Ring, um den Zugriff auf deine Wallet freizuschalten. Das Genehmigungsverfahren ist derzeit im Gange und wird in Kürze abgeschlossen sein Genehmigung läuft - Es scheint, dass die Aktivierung der Karte nicht korrekt abgeschlossen wurde. Dies kann an einem Problem mit dem NFC-Modul deines Gerätes oder an einem falschen Tippen der Karte auf dein Gerät liegen. Bitte wende dich an unser Support-Team, um Unterstützung zu erhalten. + Es scheint, dass die Aktivierung der Karte oder des Rings nicht korrekt abgeschlossen wurde. Dies kann an einem Problem mit dem NFC-Modul deines Gerätes oder an einem falschen Tippen der Karte oder Ring auf dein Gerät liegen. Bitte wende dich an unser Support-Team, um Unterstützung zu erhalten. Aktivierungsfehler Laut den Entwicklern des BNB-Netzes wird die Unterstützung für den BEP-2-Standard im Juni 2024 enden. Um den Verlust von Vermögenswerten mit diesem Standard zu vermeiden, konvertiere bitte in den BEP-20 Standard. Nutze gerne unseren Swap-Service, um sie auf das BNB Smart Chain Netzwerk zu übertragen. BNB Beacon Chain wird abgeschaltet @@ -922,7 +925,7 @@ Aktualisieren Du befindest sich derzeit im Demo-Modus Demo-Modus aktiv - Die Karte, die du gescannt hast, ist eine Entwicklerkarte. Verwenden diese nicht zur Erstellung Ihrer Wallet. + Die Karte oder Ring, die du gescannt hast, ist eine Entwicklerkarte. Verwenden diese nicht zur Erstellung Ihrer Wallet. Nicht für Benutzer! %1$s Netzwerk erfordert eine Mindesteinlage. Wenn dein Konto unter %2$s fällt, wird es deaktiviert und alle verbleibenden Guthaben werden vernichtet. Netzwerk erfordert eine Mindesteinzahlung @@ -942,21 +945,21 @@ Die Menge der zu tauschenden Token darf folgende Werte nicht überschreiten %s Der zu tauschende Betrag muss mindestens %s betragen Bitte änder den zu tauschenden Betrag - Bei dieser Karte kann es sich um ein Produktionsmuster oder eine Fälschung handeln + Bei dieser Karte oder Ring kann es sich um ein Produktionsmuster oder eine Fälschung handeln Echtheitsprüfung fehlgeschlagen zuordnen Dieser Token muss mit Ihrem Hedera-Konto verbunden sein, bevor du diesen erhalten kannst. Zuordnungsgebühr ~%1$s %2$s Dieses Token muss mit deinem Hedera-Konto verknüpft sein, bevor du ihn erhalten kannst. Verknüpfe deinen Token Nicht genug %s. Lade dein Hedera-Konto auf, um dieses Token zuzuordnen - Auf dieser Karte sind nur noch %s Unterschriften übrig. Du musst dein gesamtes Guthaben abheben. + Auf dieser Karte oder Ring oder Ring sind nur noch %s Unterschriften übrig. Du musst dein gesamtes Guthaben abheben. Geringe Anzahl von Unterschriften Token in verschiedenen Netzwerken können unterschiedliche Adressen haben. Überprüfe bei der Überweisung noch einmal, ob deine Adresse mit der des Netzwerks übereinstimmt. MATIC wird auf POL migriert. Es gibt jedoch keine Frist, und MATIC wird noch nicht abgeschafft. Du kannst MATIC-Token weiterhin verwenden oder sie über eien Exchange gegen POL tauschen. Migration von MATIC zu POL - Verwende deine Karte, um eine Adresse für das %d-Netz zu erhalten - Verwende deine Karte, um mehrere Adressen für die %d-Netzwerke zu erhalten + Verwende deine Karte oder Ring, um eine Adresse für das %d-Netz zu erhalten + Verwende deine Karte oder Ring, um mehrere Adressen für die %d-Netzwerke zu erhalten Einige Adressen fehlen Das Netzwerk ist derzeit nicht erreichbar. Bitte versuchen Sie es später erneut. @@ -964,8 +967,8 @@ Lade dein Guthaben auf Deine Wallet wurde nicht gesichert. Führe diesen Vorgang durch, um dein Vermögen jetzt zu schützen. Fehlende Sicherung - Diese Karte wurde bereits für Transaktionen verwendet. Wenn die Karte aus einer nicht vertrauenswürdigen Quelle stammt, solltest du den gesamten Betrag abheben. Wenn es sich um deine Karte handelt, sind keine Maßnahmen erforderlich. - Karte hat bereits Transaktionen unterzeichnet + Diese Karte oder Ring wurde bereits für Transaktionen verwendet. Wenn die Karte oder Ring aus einer nicht vertrauenswürdigen Quelle stammt, solltest du den gesamten Betrag abheben. Wenn es sich um deine Karte oder Ring handelt, sind keine Maßnahmen erforderlich. + Karte oder Ring hat bereits Transaktionen unterzeichnet Deine Bewertung motiviert uns, die Tangem Wallet noch besser zu machen. Gefällt dir Tangem? Du musst deinen Token zuordnen, bevor du Token erhalten kannst @@ -977,17 +980,17 @@ Das Solana-Netzwerk erhebt alle 2 Tage eine Miete von %1$s. Konten, die sich die Miete nicht leisten können, werden aus dem Netzwerk gelöscht. Hinterlege deinem Konto mit mehr als %2$s, um es kostenlos zu nutzen. Einige Netzwerke sind derzeit nicht erreichbar. Bitte versuche es später erneut. Einige Netzwerke sind nicht erreichbar - Dies ist eine Testnet-Karte. Sie kann keine Transaktionen verarbeiten und sollte nur zu Test- und Entwicklungszwecken verwendet werden. + Dies ist eine Testnet-Karte oder Ring. Sie kann keine Transaktionen verarbeiten und sollte nur zu Test- und Entwicklungszwecken verwendet werden. Nur für Testzwecke Verwerfen Du hast eine unterbrochene Sicherung. Möchtest du diese fortsetzen? Ja, fortsetzen Verwerfen - Wenn du das Backup jetzt abbrichst, musst du die Karten auf die Werkseinstellungen zurücksetzen, um von vorne zu beginnen + Wenn du das Backup jetzt abbrichst, musst du die Karten oder Ringe auf die Werkseinstellungen zurücksetzen, um von vorne zu beginnen Sicherung fortsetzen Dies ist eine unwiderrufliche Aktion Anmelden mit %s - Karte scannen - Verwenden %s oder scanne eine Karte, um auf die App zuzugreifen + Karte oder Ring scannen + Verwenden %s oder scanne eine Karte oder Ring, um auf die App zuzugreifen Willkommen zurück! diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 406280f934..ea242dd220 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -344,7 +344,7 @@ Elegir wallet La billetera no admite más de una red Para comprar, intercambiar o recibir este activo, agréguelo a su portafolio - Este activo no está disponible + Este activo no está disponible en la billetera Añadir al portafolio Agregue un token Redes disponibles diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index d7c361e8d0..301c0156c4 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -344,7 +344,7 @@ Choisissez un portefeuille Le portefeuille ne prend pas en charge plus d\'un réseau Pour acheter, échanger ou recevoir cet actif, ajoutez-le à votre portefeuille - Cet actif n\'est pas disponible + Cet actif n\'est plus pris en charge dans le portefeuille Ajouter au portfolio Ajoutez un jeton Réseaux disponibles @@ -565,8 +565,8 @@ Je comprends que je ne peux pas utiliser cette carte pour récupérer mon code d\'accès sur les autres cartes du portefeuille actuel La réinitialisation aux paramètres d\'usine supprimera complètement le portefeuille de la carte sélectionnée. Vous ne pourrez pas restaurer le portefeuille actuel ni utiliser la carte pour récupérer le code d\'accès. La réinitialisation aux paramètres d\'usine supprimera complètement le portefeuille de la carte sélectionnée et le supprimera de l\'application. Vous ne pourrez pas restaurer le portefeuille actuel. - Les propriétaires du Tangem Ring bénéficient de 3 échanges sans commission sur Changelly jusqu\'au 15/11 ! - Échangez avec 0 %% de frais maintenant! + Les propriétaires du Tangem Ring ont droit à 3 swap gratis sur Changelly jusqu\'au 15/11 ! + Échangez avec 0 %% de frais ! Avez-vous une carte bancaire d\'un autre pays et un permis de séjour ou une inscription en dehors de la Fédération de Russie ? Les cartes bancaires russes ne sont actuellement pas acceptées Connectez-vous à l\'application et vérifiez votre solde sans scanner la carte diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index fc9a95d147..f19cd32bc8 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -12,19 +12,19 @@ 取引を送信できません 選択したものは%1$sネットワークをサポートしていません。 %1$sブロックチェーンの暗号化を有効にするには、ウォレットを工場出荷時の設定にリセットする必要があります。リセットする前に出金して、資金が失われないようにしてから、リセット処理を完了してください。リセット後は、現在のウォレットにアクセスできなくなります。 - %1$s ネットワークのトークンは、ファームウェアの制限により、このカードではサポートされていません。 - カードのスキャンに問題がありますか? + %1$s ネットワークのトークンは、ファームウェアの制限により、このカードまたはリングではサポートされていません。 + カードまたはリングのスキャンに問題がありますか? このカードはこのアプリでは使用できません。 デフォルト手数料 デフォルト手数料を有効にすると、取引手数料が自動的に設定され、送金時に手数料ページを表示する必要がなくなります。必要に応じて、いつでもこのページに戻ることができます。 設定に移動して、Tangemアプリで生体認証を有効にします。 生体認証を有効にする これにより、保存されているウォレットアクセスコードがすべて削除されます。ウォレットでの今後の操作には、アクセスコードの送信が必要になります。 - 保存したカードを削除すると、保存されているすべてのウォレットとそのアクセスコードがアプリから削除されます。 + 保存したデバイスを削除すると、保存されているすべてのウォレットとそのアクセスコードがアプリから削除されます。 アクセスコードを保存 - カードとのやり取りには、アクセスコードの代わりに生体認証が要求されます。 + カードまたはリングとのやり取りには、アクセスコードの代わりに生体認証が要求されます。 ウォレットをアプリに保存する - すべてのウォレットをTangemアプリにリンクできるようにします。アプリのロックを解除するには、生体認証が必要になります。取引の署名には、Tangemカードをタップする必要があります。 + すべてのウォレットをTangemアプリにリンクできるようにします。アプリのロックを解除するには、生体認証が必要になります。取引の署名には、Tangemカードまたはリングをタップする必要があります。 ダーク ライト システムのデフォルト @@ -34,28 +34,28 @@ 今後表示しない わかりました 残高は非表示 - カードをスキャンしてください - 30秒後に再試行するか、カードをスキャンしてください。 + カードまたはリングをスキャンしてください + 30秒後に再試行するか、カードまたはリングをスキャンしてください 試行回数が多すぎます お使いの携帯電話で生体認証が無効になっているため、アプリにウォレットを保存できません。ウォレットを保存するには、携帯電話の設定で生体認証機能を有効にしてください。 バックアップ処理を開始する 銀行カードまたはその他の支払い方法を使用する - %d カード + %d デバイス - このカードを使用して、このウォレット内の他のカードのアクセスコードをリセットしたくない場合は、このオプションを無効にしてください。これにより、このカードのアクセスコードもリセットできなくなりますのでご注意ください。 + このカードを使用して、このウォレット内の他のカードまたはリングのアクセスコードをリセットしたくない場合は、このオプションを無効にしてください。これにより、このカードのアクセスコードもリセットできなくなりますのでご注意ください。 このカードを使用して、このウォレット内の他のカードのアクセスコードをリセットできます。 アクセスコードの復元 リセット 本当に実行しますか? アクセスコードの変更 アクセスコードは、このカードのみで変更されます - 選択したウォレットのすべてのカードが、工場出荷時の設定にリセットされました。これで、新しいウォレットを作成できます。 + 選択したウォレットのすべてのTangemデバイスが、工場出荷時の設定にリセットされました。これで、新しいウォレットを作成できます。 リセット完了 - このウォレットの次のカードをリセットしますか? - カードのリセット - このウォレットのすべてのカードをリセットすることをお勧めします。 - すべてのカードのリセットが完了していません。 + このウォレットの次のデバイスをリセットしますか? + ウォレットのリセット + このウォレットのすべてのTangemデバイスをリセットすることをお勧めします + すべてのTangemデバイスのリセットが完了していません 工場出荷時の設定にリセット セキュリティ・モード カード設定 @@ -132,6 +132,7 @@ わかりました プライマリーカード + プライマリーリング パスフレーズ ペースト プライバシーポリシー @@ -209,7 +210,7 @@ アクセスコード カードをスキャンする前に、正しいアクセスコードを送信する必要があります。 長くタップ - このメカニズムは、カードに対する近接攻撃から保護します。コマンドの受信と実行の間に遅延を強制します。 + このメカニズムは、カードまたはリングに対する近接攻撃から保護します。コマンドの受信と実行の間に遅延を強制します。 パスコード カードの状態の変更を伴うコマンドを実行する前に、パスコードを入力する必要があります。 紹介プログラム @@ -226,7 +227,7 @@ 詳細 インターネット接続を確認するか、別のネットワークに切り替えてください。 利用規約 - 別のウォレットのカードを使用しました。このウォレットに関連付けられているカードをタップしてください。 + 別のウォレットのカードまたはリングを使用しました。このウォレットにリンクしているカードまたはリングをタップしてください。 マイトークン まだトークンを追加していません。マーケットからトークンを追加して交換してください。 %sとの交換はできません @@ -283,11 +284,11 @@ ポートフォリオ内のアセットをこのトークンと交換する 以下の情報はオプションです。共有したくない場合は消去できます。 どのような機能が不足しているかを教えください。解決できるよう尽力致します。 - お持ちのカードについて教えてください + お持ちのカードまたはリングについて教えてください サポートチームの皆さん、こんにちは。 問題について詳しく教えてください。どんな些細なことでも役に立ちます。 私の提案 - カードをスキャンできません + カード / リングをスキャンできません フィードバック Tangemへのフィードバック 取引を送信できません @@ -301,17 +302,18 @@ 続行するには、%1sスマートコントラクトに%2sを使用する権限を付与してください 許可を与える 無制限 - カードを注文 - スキャン + Tangemを注文 + Tangemをスキャン この情報はAIによって生成されました - アクセスコードを変更するには、上図のようにカードをタップし、操作が終了するまで取り外さないでください。 + アクセスコードを変更するには、上図のようにカードまたはリングをタップし、操作が終了するまで取り外さないでください。 パスコードを変更するには、上記のようにカードをタップし、操作が終了するまで取り外さないでください。 ウォレットを作成するには、上記のようにカードをタップし、操作が終了するまで取り外さないでください。 + ウォレットを作成するには、上図のようにリングをタップし、操作が終了するまで取り外さないでください。 ウォレットの%s番目のカードをタップします タップしてスキャン タップして署名 - カードをタップ - 生体認証を更新しました。カードをスキャンして入ってください。 + カードまたはリングをタップ + 生体認証を更新しました。カードまたはリングをスキャンして入ってください。 送金するには、残高が手数料額より高くなければなりません。 残高不足 この取引に必要なManaが不足しています。Manaが補充されるまでお待ちください。あなたのMana残高は%1$s/%2$sです。 @@ -323,7 +325,7 @@ 暗号資産および取引の追跡を開始するには、トークンを追加してください トークンの管理 すべてのネットワークにアクセスするには、カードをスキャンする必要があります。 - カードをスキャンする + カードまたはリングをスキャンする 2月%2$s - %3$sの期間、Changelly経由のスワップは%1$sのサービス手数料となります。 Changellyでスワップ、手数料%s トークン @@ -356,7 +358,7 @@ 利用可能なネットワーク 私のポートフォリオ マーケット - 選択したネットワークのアドレスを生成するには、Tangemカードをスキャンする必要があります。 + 選択したネットワークのアドレスを生成するには、Tangemウォレットカードまたはリングをスキャンする必要があります。 トークンを追加するには、これをスワイプするか、検索バーをタップしてください。 このセクションのデータは、次のネットワークから取得されています: %s データを読み込めません… @@ -446,11 +448,11 @@ これをドラッグするか、検索窓をタップして、マーケットから直接トークンを追加します トークンを追加 お使いのデバイスではNFCが使用できません - すべてのカードを保護するには、単一のアクセスコードを設定する必要があります + すべてのデバイスを保護するには、単一のアクセスコードを設定してください。 保護する - 後で各カードに個別のアクセスコードを設定できます + 後で各カードおよびリングに個別のアクセスコードを設定できます。 パーソナライズする - アクセスコードはリンクされたカード1枚で復元できます。すべてのカードを1か所に保管しないでください。 + アクセスコードはリンクされたカードおよびリング1つで復元できます。すべてのデバイスを1か所に保管しないでください。 復元する アクセスコードとして任意の単語、フレーズ、または数字を選択してください アクセスコードの作成 @@ -461,24 +463,26 @@ 操作を繰り返してください。カードは工場出荷時の設定にリセットされます。 アクティベーションに失敗しました トークンを追加する - バックアップカードを1枚追加しました。バックアップ処理が終了すると、これ以上バックアップカードを追加することはできません。もう一枚カードがあれば、バックアップに追加してください。バックアップ処理を続けますか? + バックアップカードまたはリングを1つ追加しました。バックアップ処理が終了すると、これ以上バックアップデバイスを追加することはできません。もう一つカードまたはリングがある場合、バックアップに追加してください。バックアップ処理を続けますか? バックアップ手続きは部分的に完了しています。現在終了することはできません。 パスフレーズは、暗号資産ウォレットが使用する高度なセキュリティ機能です。既存のリカバリフレーズに、自分で選択した単語またはフレーズを追加することで、まったく新しいアドレスのロック解除が可能になります。 - バックアップカードを追加する + バックアップ用のカードまたはリングを追加 + カードをスキャン カード #%d をスキャン 今すぐバックアップ - プライマリカードをスキャン + カードをスキャン + リングをスキャン ウォレットへ進む バックアップを完了する 暗号資産を受け取る プライマリカードをスキャン スキップする どのように機能しますか? - すべての秘密鍵をカード内で生成し、安全なウォレットを作成しましょう + すべての秘密鍵をカードまたはリング内で生成し、安全なウォレットを作成しましょう ウォレットを作成する ウォレットを作成する その他のオプション - 秘密鍵はカード内で安全に生成されます。シードフレーズは存在しないので、誰もエクスポートしたり盗んだりすることはできません。 + 秘密鍵はカードまたはリング内で安全に生成されます。シードフレーズは存在しないので、誰もエクスポートしたり盗んだりすることはできません。 秘密鍵を非公開で生成する カードは有効化され、使用可能になりました 成功! @@ -498,27 +502,30 @@ ウォレットをインポートするには、下のフィールドにシードフレーズを入力してください。 シードフレーズを生成する ウォレットをインポート - シードフレーズは、ウォレットを復元できる一連の単語です。カードによって生成される秘密鍵とは異なり、シードフレーズは保護されていないため、コピーされて盗まれる可能性があります。このオプションは自己責任で使用してください。 + シードフレーズは、ウォレットを復元できる一連の単語です。カードやリングによって生成される秘密鍵とは異なり、シードフレーズは保護されていないため、コピーされて盗まれる可能性があります。このオプションは自己責任で使用してください。 シードフレーズを使用する 無効なシードフレーズです。語順を確認してください。 無効なシードフレーズです。スペルを確認してください。 レガシー シードフレーズを正しく書き込んだかどうかを確認するために、2番目、7番目、11番目の単語を入力してください。 では、確認してみましょう - バックアップ処理を開始するには、最大2枚のバックアップカードを追加します。 - カードをもう1枚追加するか、バックアップ処理を完了します + バックアップ処理を開始するには、最大2つのバックアップカードまたはリングを追加します。 + カードまたはリングをもう1つ追加するか、バックアップ処理を完了します 番号%sのバックアップカードを準備してください - プライマリカードをスキャンして、バックアップ処理を開始します。 + プライマリカードまたはリングをスキャンして、バックアップ処理を開始します。 番号%sのプライマリカードを準備してください - ウォレットカードが設定され、使用できるようになりました。 - 最大枚数のカードが追加されました。バックアップ処理を完了します。 - カードの有効化 + リングを準備して、下のスキャンボタンを押してください + ウォレットが設定され、使用できるようになりました。 + 最大数のデバイスが追加されました。バックアップ処理を完了します。 + ウォレットの有効化 + バックアップカード バックアップカード # %d - バックアップカードなし + バックアップリング + バックアップカードまたはリングなし 通知 - バックアップカードが1枚追加されました + バックアップデバイスが1つ追加されました カードを準備してください - バックアップカード2枚が追加されました + バックアップデバイス2つが追加されました 始めるには、ウォレットに任意の金額を入金するだけです 始めるには、ウォレットに%1$s %2$s以上入金するだけです 暗号資産を購入する @@ -526,7 +533,7 @@ ウォレットを有効化する ツイン化プロセスは部分的に完了しています。現在終了することはできません。 ウォレットの作成プロセスが何らかの理由で中断された場合は、最初からやり直す必要があります。 - 秘密鍵のバックアップは、未使用のTangemウォレットカード2枚まで可能です。 + 秘密鍵のバックアップは、未使用のTangemウォレットカードまたはリング2つまで可能です。 アクセスコードは、バックアップカード1枚を使用して復元できます。 すべてのバックアップカードは同一の秘密鍵を使用しており、すべての機能を使用できます。 ウォレットを保護するためにアクセスコードを設定できます。 @@ -575,13 +582,13 @@ カードをリセットする この操作を実行すると、現在のウォレットにアクセスできなくなることを理解しています。 このカードを使用して、現在のウォレットの他のカードのアクセスコードを回復させられないことを認識しています。 - 工場出荷時設定にリセットすると、選択したカードからウォレットが完全に削除されます。現在のウォレットを復元したり、カードを使用してアクセスコードを回復したりすることはできません。 - 工場出荷時の状態にリセットすると、選択したカードからウォレットが完全に削除され、アプリから削除されます。現在のウォレットを復元することはできません。 + 工場出荷時設定にリセットすると、選択したカードやリングからウォレットが完全に削除されます。現在のウォレットを復元したり、カードやリングを使用してアクセスコードを復元することはできません。 + 工場出荷時の状態にリセットすると、選択したカードやリングからウォレットが完全に削除され、アプリから削除されます。現在のウォレットを復元することはできません。 Tangem Ringユーザーは、11/15日までChangelly経由でスワップを3回手数料ゼロで行えます! 今すぐ手数料0%でスワップしましょう! 他の国の銀行カードと、ロシア連邦外での居住許可証または登録をお持ちですか? ロシアの銀行カードは現在ご利用いただけません - アプリにログインして、カードをスキャンせずに残高を確認できます + アプリにログインして、カードまたはリングをスキャンせずに残高を確認できます アプリにアクセスする 生体認証の使用を許可する ウォレットの操作には、アクセスコードの代わりに生体認証が要求されます。 @@ -589,10 +596,10 @@ 生体認証が無効になっているようです。ウォレットを保存する必要があります。 生体認証を有効にする 生体認証を使用しますか? - 資金を使って取引を行うには、カードが必要になりますのでご注意ください。 - カードをスキャン - カードをスキャンして設定を変更します。変更はスキャンしたカードにのみ影響し、ウォレットに関連付けられている他のカードには影響しません。 - カードを準備してください! + 資金を使って取引を行うには、カードまたはリングが必要になりますのでご注意ください + カードまたはリングをスキャン + カードまたはリングをスキャンして設定を変更します。変更はスキャンしたカードまたはリングにのみ影響し、ウォレットに関連付けられている他のデバイスには影響しません。 + Tangemを準備してください! 入力したアドレスにすでに含まれています 手数料額が推奨額の%s倍となっています。設定を再度確認し、調整してください。 推奨手数料を下回る手数料が指定されたため、取引に遅れが生じる可能性があります。続行しますか? @@ -668,7 +675,7 @@ 取引は正常に署名され、ブロックチェーンノードに送信されました。ウォレットの残高はしばらくして更新されます。 %1$sはTronネットワークのアセットです。手数料を計算して取引を行うには、アカウントにTron(TRX)を入金する必要があります。 取引が送信されました - セットアップしたいカードをスキャンするために準備してください。 + 設定したいカードまたはリングをスキャンするために準備してください。 ウォレット削除 これにより、ウォレットがアプリから削除されます。ウォレットは再度追加できます。 名前 @@ -692,7 +699,7 @@ 請求中の報酬 ステーキング報酬の受け取り方法。\n自動であなたのアドレスに報酬が入金される方法と、手動で取引を生成して報酬を引き出す方法があります。 報酬スケジュール - これは、ステーキングの参加者がいつ報酬を受け取るかを決定するスケジュールです。 + これは、ステーキングの参加者が報酬を受け取る時期を決定するスケジュールです。報酬の配布時間は、バリデーターとネットワークの負荷に応じて若干異なる場合があります。 報酬: %s ステーキング%s 解約完了までの期間 @@ -744,7 +751,7 @@ 報酬 ステーキングはロックされています もっとステーキングする - %1$sをステーキングし、年間 %2$sを受け取ります + %1$sをステーキングし、毎%2$s報酬を受け取ります タップしてロック解除 タップしてロック解除もしくは投票 タップして引き出す @@ -764,13 +771,13 @@ 投票する 引き出す あなたのステーキング - カード内に秘密鍵を保管しながら暗号資産を安全に保管します + カードまたはリング内に秘密鍵を保管しながら、暗号資産を安全に保管します 革新的なハードウェアウォレット - 1つのウォレットに最大3枚のカード + 1つのウォレットに最大3枚のカードまたは3本のリング 安全なバックアップ - ビットコイン、イーサリアム、その他多くの暗号資産を同時に管理できるハードウェアウォレット – オールインワンカード + ビットコイン、イーサリアム、その他多くの暗号資産を同時に管理できるハードウェアウォレット – オール・イン・ワンのカード / リング 数千の通貨 - 外出先でも、いつでもどこでも使用できます。コードや電池は不要です。暗号資産が必要なときに、カードをスマートフォンにタップするだけです。 + 外出先でも、いつでもどこでも使用できます。コードや電池は不要です。暗号資産が必要なときに、カードまたはリングをスマートフォンにタップするだけです。 すべての人のためのウォレット Tangemのご紹介 100種類以上の分散型サービスで、NFTの交換・購入や、借入・預金を行うことができます。 @@ -838,13 +845,13 @@ Tangemツイン この操作は元に戻せません。古いウォレットにはアクセスできなくなります。 番号%sのツインカードをタップし、操作が終了するまで取り外さないでください。 - %sを使用するか、カードをスキャンしてウォレットにアクセスしてください + %sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください 最新の機能とニュースをお届けします 新しいプロモーション情報をいち早く入手しましょう プッシュ通知を使用しますか? 新しいウォレットを追加 本当にこのウォレットを削除してもよろしいですか? - エラーが発生しました。カードをスキャンしてログインしてください。 + エラーが発生しました。カードまたはリングをスキャンしてログインしてください。 このウォレットはすでに保存されています。別のウォレットを追加できます。 %sという名前のウォレットはすでに存在します。 ウォレット名 @@ -852,7 +859,7 @@ すべてのロックを解除 %sですべてをロック解除 ブロックチェーンにアクセスできません。後でもう一度お試しください。 - カードをスキャン + カードまたはリングをスキャン メッセージに署名することを要求しています。 \n\n %s Dapp%1$s 、BNB取引の署名を要求しています\n\n%2$s %1$sの取引注文\n価格: %2$s\n受取金額: %3$s\n支払金額: %4$s @@ -866,7 +873,7 @@ セッションリクエストには、WalletConnect接続でサポートされていないブロックチェーンが含まれています。サポートされていないブロックチェーン: \n 技術的な実装のため、このDappとの接続は確立できません。 不明なエラーが発生しました。エラーメッセージ: %s 。問題が解決しない場合は、お気軽にサポートにお問い合わせください。 - Tangemアプリで間違ったカードが選択されました + Tangemアプリで誤ったカードまたはリングが選択されました Dappデータから取引を作成できませんでした。コード: %s 不明なエラーが発生しました。エラーコード: %d 。問題が解決しない場合は、お気軽にサポートにお問い合わせください。 WalletConnectセッションが開かれていません @@ -891,10 +898,10 @@ インターネット接続がありません ウォレット設定 Tangem - %sを使用するか、カードをスキャンしてウォレットにアクセスしてください + %sを使用するか、カード / リングをスキャンしてウォレットにアクセスしてください 許可付与のプロセスは現在進行中であり、まもなく完了する予定です。 承認中 - カードのアクティベーションが正しく完了しませんでした。デバイスの NFCモジュールに問題があるか、カードをデバイスに正しくタップしていないことが原因かもしれません。サポートチームにお問い合わせください。 + カードまたはリングのアクティベーションが正しく完了しませんでした。デバイスのNFCモジュールに問題があるか、カードまたはリングをデバイスに正しくタップしていないことが原因かもしれません。サポートチームにお問い合わせください。 アクティベーションに失敗しました BNBネットワーク開発者によると、BEP-2規格のサポートは2024年6月に終了します。この規格の資産を失わないために、BEP-20規格に変換してください。BNBスマートチェーンネットワークへ移行するには、Tangemのスワップサービスをご利用ください。 BNBビーコンチェーンは閉鎖されます。 @@ -940,7 +947,7 @@ MATICはPOLに移行中です。ただし、期限は設定されておらず、MATICはまだ廃止されていません。MATICトークンを引き続き安全に使用することも、取引所でPOLに交換することもできます。 MATICからPOLへの移行 - %d ネットワークのアドレスを取得するために、カードを利用してください + %d ネットワークのアドレスを取得するために、カードまたはリングを利用してください 一部のアドレスが見つかりません 現在、ネットワークにアクセスできません。しばらくしてからもう一度お試しください。 @@ -967,11 +974,11 @@ バックアップが中断されました。再開しますか? はい、再開します 破棄 - バックアップを破棄する場合は、カードを工場出荷時の設定にリセットしてやり直す必要があります。 + バックアップを破棄する場合は、デバイスを工場出荷時の設定にリセットしてやり直す必要があります。 バックアップを再開する これはやり直しができないアクションです %sでログイン - カードをスキャン - アプリにアクセスするには、 %sを使用するか、カードをスキャンしてください + カードまたはリングをスキャン + アプリにアクセスするには、 %sを使用するか、カードまたはリングをスキャンします お帰りなさい! diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 9cf2227dc0..3ac533d36e 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -52,7 +52,7 @@ Сбросить Вы уверены, что хотите это сделать? Смена кода доступа - Код доступа будет изменен только на данной карте + Код доступа будет изменен только на данной карте или кольце Все устройства Tangem выбранного кошелька сброшены до заводских настроек, вы можете создать новый кошелек Сброс завершён Хотите сбросить следующее устройство от этого кошелька? @@ -61,7 +61,7 @@ Вы сбросили не все Tangem устройства Заводские настройки Тип безопасности - Настройки карты + Настройки устройства Помимо сетевой комиссий, сеть Cardano взимает %1$s ADA при транзакции с токеном %2$s Требования к транзакции Cardano Чтобы совершить транзакцию %1$s, внесите некоторую сумму ADA для покрытия сетевой комиссии и минимального значения ADA (рекомендуется 5 ADA) @@ -131,6 +131,7 @@ Осталось %1$s Заблокирован Основная сеть + месяц Сетевая комиссия Сумма отправки будет уменьшена на %1$s (%2$s) для покрытия выбранного уровня комиссии Далее @@ -222,7 +223,7 @@ Реферальная программа Переверните экран вашего устройства вниз, чтобы быстро скрыть и отобразить балансы %s хэшей - Номер карты + Номер устройства Обратиться в поддержку Добавить еще карты Валюта приложения @@ -496,7 +497,7 @@ Создать кошелек Создать кошелек Другие опции - Ваши ключи будут надежно сгенерированы внутри карты или кольца. Никакой seed-фразы, а это значит, что никто не может экспортировать или украсть ее. + Ваши ключи будут надежно сгенерированы внутри чипа. Никакой seed-фразы, а это значит, что никто не может экспортировать или украсть ее. Cоздавайте ключи приватно Ваша карта активирована и готова к использованию Успешно! @@ -534,11 +535,14 @@ Подготовьте резервную карту с номером %s Отсканируйте основную карту или кольцо, чтобы начать процесс резервного копирования. Подготовьте основную карту с номером %s + Приготовьте кольцо и нажмите кнопку сканирования кольца внизу Ваш кошелек настроен и готов к использованию. Добавлено максимальное количество устройств. Завершите процесс резервного копирования. Активация кошелька + Резервная карта Резервная карта #%d - Нет резервных карт или колец + Резервное кольцо + Нет резервных устройств Уведомления Добавлено одно резервное устройство Подготовьте свою карту diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index de1de7537b..513cd8eba2 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -50,7 +50,7 @@ Reset Are you sure you want to do this? Change Access Code - Access code will be changed on this card only + Access code will be changed on this card or ring only All Tangem devices in the selected wallet have been reset to factory settings. You can now create a new wallet. Reset complete Do you want to reset the next device in this wallet? @@ -59,7 +59,7 @@ You haven\'t reset all your Tangem devices Reset to Factory Settings Security Mode - Card settings + Device settings In addition to network fee, the Cardano network charges %1$s ADA when transacting with the %2$s token Cardano transaction requirements To make a %1$s transaction, you must deposit some ADA to cover the network fee and minimum ADA value (5 ADA recommended) @@ -219,7 +219,7 @@ Referral program Flip your device screen down to quickly hide and show balances %s hashes - Card ID + Device ID Contact support Link More Cards App Currency @@ -488,7 +488,7 @@ Create wallet Create a wallet Other options - Your keys will be securely generated inside the card or ring. There is no seed phrase, which means nobody can export or steal it. + Your keys will be securely generated inside the chip. There is no seed phrase, which means nobody can export or steal it. Generate keys privately Your card is activated and ready to be used Success! @@ -522,11 +522,14 @@ Prepare the backup card with number %s Scan the primary card or ring to start the backup process. Prepare the primary card with number %s + Prepare the ring and press the scan button below Your wallet is configured and ready for use. Max number of devices added. Finalize the backup process. Activating wallet + Backup card Backup card #%d - No backup cards or rings + Backup ring + No backup devices Notifications One backup device added Prepare your card diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt index 41c22e6cbd..cd7b4d5852 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/Notification.kt @@ -179,14 +179,20 @@ private fun Icon(@DrawableRes iconResId: Int, tint: Color?, modifier: Modifier = } @Composable -private fun TextsBlock(title: TextReference?, subtitle: TextReference, subtitleColor: Color) { - Column { +internal fun TextsBlock( + title: TextReference?, + subtitle: TextReference, + subtitleColor: Color, + modifier: Modifier = Modifier, + titleColor: Color = TangemTheme.colors.text.primary1, +) { + Column(modifier = modifier) { val titleText = title?.resolveReference() if (titleText != null) { Text( text = titleText, - color = TangemTheme.colors.text.primary1, + color = titleColor, style = TangemTheme.typography.button, ) @@ -269,7 +275,12 @@ private fun PairButtons(config: NotificationButtonsState.PairButtonsConfig, isEn } @Composable -private fun CloseableIconButton(onClick: (() -> Unit)?, modifier: Modifier = Modifier, isEnabled: Boolean = true) { +internal fun CloseableIconButton( + onClick: (() -> Unit)?, + modifier: Modifier = Modifier, + isEnabled: Boolean = true, + iconTint: Color = TangemTheme.colors.icon.inactive, +) { AnimatedVisibility(visible = onClick != null, modifier = modifier) { onClick ?: return@AnimatedVisibility @@ -296,7 +307,7 @@ private fun CloseableIconButton(onClick: (() -> Unit)?, modifier: Modifier = Mod modifier = Modifier .size(size = TangemTheme.dimens.size16) .align(alignment = Alignment.Center), - tint = TangemTheme.colors.icon.inactive, + tint = iconTint, ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/RingPromoNotification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/RingPromoNotification.kt new file mode 100644 index 0000000000..c40947749d --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/RingPromoNotification.kt @@ -0,0 +1,131 @@ +package com.tangem.core.ui.components.notifications + +import android.content.res.Configuration +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.FixedScale +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import com.tangem.core.ui.R +import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.res.TangemColorPalette +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview + +@Composable +fun RingPromoNotification(config: NotificationConfig, modifier: Modifier = Modifier) { + var textHeightDp by remember { mutableStateOf(0.dp) } + + Box( + modifier = modifier + .fillMaxWidth() + .clip(shape = TangemTheme.shapes.roundedCornersXMedium) + .background(TangemColorPalette.Dark6), + ) { + PromoImage( + backgroundRes = config.backgroundResId, + iconRes = config.iconResId, + modifier = Modifier.height(textHeightDp), + ) + PromoText( + title = config.title, + subtitle = config.subtitle, + onSizeChange = { textHeightDp = it }, + ) + CloseableIconButton( + onClick = config.onCloseClick, + modifier = Modifier.align(alignment = Alignment.TopEnd), + iconTint = TangemTheme.colors.icon.informative, + ) + } +} + +@Composable +private fun PromoImage(@DrawableRes backgroundRes: Int?, @DrawableRes iconRes: Int, modifier: Modifier = Modifier) { + if (backgroundRes == null) return + ConstraintLayout( + modifier = modifier, + ) { + val (background, image) = createRefs() + + Image( + painter = painterResource(backgroundRes), + contentDescription = null, + contentScale = FixedScale(2f), + modifier = Modifier + .constrainAs(background) { + top.linkTo(parent.top) + start.linkTo(image.start) + end.linkTo(image.end) + }, + ) + Image( + painter = painterResource(id = iconRes), + contentDescription = null, + contentScale = ContentScale.FillWidth, + modifier = Modifier + .requiredWidth(width = 60.dp) + .wrapContentHeight(Alignment.Top, unbounded = true) + .constrainAs(image) { + top.linkTo(parent.top, 11.dp) + start.linkTo(parent.start, 9.dp) + }, + ) + } +} + +@Composable +private fun PromoText(title: TextReference?, subtitle: TextReference, onSizeChange: (Dp) -> Unit) { + val density = LocalDensity.current + + Box( + modifier = Modifier.onSizeChanged { + with(density) { onSizeChange(it.height.toDp()) } + }, + ) { + TextsBlock( + title = title, + subtitle = subtitle, + subtitleColor = TangemTheme.colors.text.tertiary, + titleColor = TangemTheme.colors.text.constantWhite, + modifier = Modifier + .wrapContentHeight() + .align(Alignment.CenterStart) + .padding(start = 80.dp, top = 12.dp, end = 12.dp, bottom = 12.dp), + ) + } +} + +// region Preview +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, locale = "fr") +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun RingPromoNotification_Preview() { + TangemThemePreview { + RingPromoNotification( + NotificationConfig( + title = resourceReference(id = R.string.ring_promo_title), + subtitle = resourceReference(id = R.string.ring_promo_text), + iconResId = R.drawable.img_card_with_ring, + backgroundResId = R.drawable.img_ring_promo_background, + onCloseClick = { }, + ), + ) + } +} + +// endregion \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/img_card_with_ring.webp b/core/ui/src/main/res/drawable/img_card_with_ring.webp new file mode 100644 index 0000000000..c4c8010355 Binary files /dev/null and b/core/ui/src/main/res/drawable/img_card_with_ring.webp differ diff --git a/core/ui/src/main/res/drawable/img_ring_promo_background.webp b/core/ui/src/main/res/drawable/img_ring_promo_background.webp new file mode 100644 index 0000000000..aa5ae8be39 Binary files /dev/null and b/core/ui/src/main/res/drawable/img_ring_promo_background.webp differ diff --git a/data/card/build.gradle.kts b/data/card/build.gradle.kts index eb8abfb89e..eb80b3d8cf 100644 --- a/data/card/build.gradle.kts +++ b/data/card/build.gradle.kts @@ -26,6 +26,8 @@ dependencies { implementation(projects.core.datasource) implementation(projects.core.utils) + implementation(projects.libs.blockchainSdk) + implementation(projects.domain.card) implementation(projects.domain.models) } \ No newline at end of file diff --git a/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt b/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt index a8495e8308..cb9495d708 100644 --- a/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt +++ b/data/card/src/main/java/com/tangem/data/card/DefaultCardSdkConfigRepository.kt @@ -1,7 +1,8 @@ package com.tangem.data.card import com.tangem.TangemSdk -import com.tangem.blockchain.common.CommonSigner +import com.tangem.blockchain.common.TransactionSigner +import com.tangem.blockchainsdk.signer.TransactionSignerFactory import com.tangem.common.UserCodeType import com.tangem.common.core.CardIdDisplayFormat import com.tangem.common.core.UserCodeRequestPolicy @@ -16,7 +17,10 @@ import com.tangem.domain.models.scan.ProductType * [REDACTED_AUTHOR] */ -internal class DefaultCardSdkConfigRepository(private val cardSdkProvider: CardSdkProvider) : CardSdkConfigRepository { +internal class DefaultCardSdkConfigRepository( + private val cardSdkProvider: CardSdkProvider, + private val transactionSignerFactory: TransactionSignerFactory, +) : CardSdkConfigRepository { @Deprecated("Use CardSdkConfigRepository's methods instead of this property") override val sdk: TangemSdk @@ -47,11 +51,9 @@ internal class DefaultCardSdkConfigRepository(private val cardSdkProvider: CardS } } - override fun getCommonSigner(cardId: String?) = CommonSigner( - tangemSdk = sdk, - cardId = cardId, - initialMessage = null, - ) + override fun getCommonSigner(cardId: String?): TransactionSigner { + return transactionSignerFactory.createTransactionSigner(cardId = cardId, sdk = sdk) + } override fun isLinkedTerminal() = sdk.config.linkedTerminal diff --git a/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt b/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt index eb53f5dea1..cfdd7984b5 100644 --- a/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt +++ b/data/card/src/main/java/com/tangem/data/card/di/CardDataModule.kt @@ -1,5 +1,6 @@ package com.tangem.data.card.di +import com.tangem.blockchainsdk.signer.TransactionSignerFactory import com.tangem.data.card.DefaultCardRepository import com.tangem.data.card.DefaultCardSdkConfigRepository import com.tangem.data.card.sdk.CardSdkProvider @@ -18,8 +19,14 @@ internal object CardDataModule { @Provides @Singleton - fun provideCardSdkConfigRepository(cardSdkProvider: CardSdkProvider): CardSdkConfigRepository { - return DefaultCardSdkConfigRepository(cardSdkProvider = cardSdkProvider) + fun provideCardSdkConfigRepository( + cardSdkProvider: CardSdkProvider, + transactionSignerFactory: TransactionSignerFactory, + ): CardSdkConfigRepository { + return DefaultCardSdkConfigRepository( + cardSdkProvider = cardSdkProvider, + transactionSignerFactory = transactionSignerFactory, + ) } @Provides diff --git a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt index 94a184fb73..fbd89738aa 100644 --- a/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt +++ b/data/promo/src/main/java/com/tangem/data/promo/DefaultPromoRepository.kt @@ -41,9 +41,19 @@ internal class DefaultPromoRepository( }.getOrNull() } + override suspend fun getRingPromoBanner(): PromoBanner? { + return runCatching(dispatchers.io) { + promoResponseConverter.convert( + tangemApi.getPromotionInfo(RING) + .getOrThrow(), + ) + }.getOrNull() + } + private companion object { private const val CHANGELLY_NAME = "changelly" private const val TRAVALA = "travala" private const val OKX = "okx" + private const val RING = "ring" } } \ No newline at end of file diff --git a/data/settings/build.gradle.kts b/data/settings/build.gradle.kts index 6856b1236f..992a502c03 100644 --- a/data/settings/build.gradle.kts +++ b/data/settings/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { implementation(projects.domain.balanceHiding.models) implementation(projects.domain.settings) + implementation(projects.domain.wallets.models) implementation(deps.androidx.datastore) diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt index ce6d3fa236..ecd647ae73 100644 --- a/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt +++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultPromoSettingsRepository.kt @@ -1,13 +1,18 @@ package com.tangem.data.settings import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY import com.tangem.datasource.local.preferences.PreferencesKeys.IS_TOKEN_SWAP_PROMO_OKX_SHOW_KEY import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_SWAP_PROMO_OKX_SHOW_KEY import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_TRAVALA_PROMO_SHOWN_KEY +import com.tangem.datasource.local.preferences.PreferencesKeys.SHOULD_SHOW_RING_PROMO_KEY import com.tangem.datasource.local.preferences.utils.get import com.tangem.datasource.local.preferences.utils.store import com.tangem.domain.settings.repositories.PromoSettingsRepository +import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map /** * Repository for showing swap promo notification. @@ -47,4 +52,18 @@ class DefaultPromoSettingsRepository( value = false, ) } + + override fun isReadyToShowRingPromo(userWalletId: UserWalletId): Flow { + return combine( + flow = appPreferencesStore + .get(key = ADDED_WALLETS_WITH_RING_KEY, default = emptySet()) + .map { userWalletId.stringValue in it }, + flow2 = appPreferencesStore.get(key = SHOULD_SHOW_RING_PROMO_KEY, default = true), + transform = { isRingAdded, shouldShowRingPromo -> isRingAdded && shouldShowRingPromo }, + ) + } + + override suspend fun setNeverToShowRingPromo() { + appPreferencesStore.store(key = SHOULD_SHOW_RING_PROMO_KEY, value = false) + } } \ No newline at end of file diff --git a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt index b18a5b0fa4..8a4472cf71 100644 --- a/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt +++ b/data/transaction/src/main/java/com/tangem/data/transaction/DefaultTransactionRepository.kt @@ -146,7 +146,7 @@ internal class DefaultTransactionRepository( override suspend fun sendTransaction( txData: TransactionData, - signer: CommonSigner, + signer: TransactionSigner, userWalletId: UserWalletId, network: Network, ) = withContext(coroutineDispatcherProvider.io) { @@ -161,7 +161,7 @@ internal class DefaultTransactionRepository( override suspend fun sendMultipleTransactions( txsData: List, - signer: CommonSigner, + signer: TransactionSigner, userWalletId: UserWalletId, network: Network, ) = withContext(coroutineDispatcherProvider.io) { diff --git a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt index 2cc72cd098..b7102a6b52 100644 --- a/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt +++ b/data/wallets/src/main/java/com/tangem/data/wallets/DefaultWalletsRepository.kt @@ -5,6 +5,7 @@ import com.tangem.datasource.local.preferences.PreferencesKeys import com.tangem.datasource.local.preferences.utils.get import com.tangem.datasource.local.preferences.utils.getSyncOrDefault import com.tangem.datasource.local.preferences.utils.store +import com.tangem.domain.wallets.models.UserWalletId import com.tangem.domain.wallets.repository.WalletsRepository import kotlinx.coroutines.flow.Flow @@ -23,4 +24,18 @@ internal class DefaultWalletsRepository( override suspend fun saveShouldSaveUserWallets(item: Boolean) { appPreferencesStore.store(key = PreferencesKeys.SAVE_USER_WALLETS_KEY, value = item) } + + override suspend fun isWalletWithRing(userWalletId: UserWalletId): Boolean { + return appPreferencesStore + .getSyncOrDefault(key = PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY, default = emptySet()) + .contains(element = userWalletId.stringValue) + } + + override suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) { + appPreferencesStore.editData { + val added = it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY].orEmpty() + + it[PreferencesKeys.ADDED_WALLETS_WITH_RING_KEY] = added + userWalletId.stringValue + } + } } \ No newline at end of file diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardSdkConfigRepository.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardSdkConfigRepository.kt index 287ddd37cd..ef277955c2 100644 --- a/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardSdkConfigRepository.kt +++ b/domain/card/src/main/kotlin/com/tangem/domain/card/repository/CardSdkConfigRepository.kt @@ -1,7 +1,7 @@ package com.tangem.domain.card.repository import com.tangem.TangemSdk -import com.tangem.blockchain.common.CommonSigner +import com.tangem.blockchain.common.TransactionSigner import com.tangem.domain.models.scan.ProductType /** @@ -25,7 +25,7 @@ interface CardSdkConfigRepository { fun updateCardIdDisplayFormat(productType: ProductType) /** Get common signer by [cardId] */ - fun getCommonSigner(cardId: String?): CommonSigner + fun getCommonSigner(cardId: String?): TransactionSigner /** Check if linked terminal is enabled */ fun isLinkedTerminal(): Boolean? diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt index 6d6c0b3a4b..5a531976c7 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/DefaultWalletManagersFacade.kt @@ -614,7 +614,7 @@ class DefaultWalletManagersFacade( override suspend fun associateAsset( userWalletId: UserWalletId, currency: CryptoCurrency, - signer: CommonSigner, + signer: TransactionSigner, ): SimpleResult { return withContext(dispatchers.io) { val walletManager = getOrCreateWalletManager(userWalletId = userWalletId, network = currency.network) diff --git a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt index 5104db3554..2f6317a316 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/walletmanager/WalletManagersFacade.kt @@ -236,7 +236,7 @@ interface WalletManagersFacade { suspend fun associateAsset( userWalletId: UserWalletId, currency: CryptoCurrency, - signer: CommonSigner, + signer: TransactionSigner, ): SimpleResult /** diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt index fcce746f21..706e05a1e5 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt @@ -323,5 +323,6 @@ data class CardDTO( companion object { val RING_BATCH_IDS = listOf("AC17", "BA01") + const val RING_BATCH_PREFIX = "BA" } } \ No newline at end of file diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/RingExt.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/RingExt.kt new file mode 100644 index 0000000000..d2ce46707e --- /dev/null +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/RingExt.kt @@ -0,0 +1,8 @@ +package com.tangem.domain.models.scan + +import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_IDS +import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_PREFIX + +fun isRing(batchId: String): Boolean { + return RING_BATCH_IDS.contains(batchId) || batchId.startsWith(RING_BATCH_PREFIX) +} \ No newline at end of file diff --git a/domain/settings/build.gradle.kts b/domain/settings/build.gradle.kts index 0c8b0de6e1..7b8e6bc2ad 100644 --- a/domain/settings/build.gradle.kts +++ b/domain/settings/build.gradle.kts @@ -7,4 +7,5 @@ dependencies { implementation(deps.kotlin.coroutines) implementation(deps.arrow.core) implementation(projects.domain.balanceHiding.models) + implementation(projects.domain.wallets.models) } \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowRingPromoUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowRingPromoUseCase.kt new file mode 100644 index 0000000000..67d9174e78 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowRingPromoUseCase.kt @@ -0,0 +1,14 @@ +package com.tangem.domain.settings + +import com.tangem.domain.settings.repositories.PromoSettingsRepository +import com.tangem.domain.wallets.models.UserWalletId +import kotlinx.coroutines.flow.Flow + +class ShouldShowRingPromoUseCase(private val promoSettingsRepository: PromoSettingsRepository) { + + operator fun invoke(userWalletId: UserWalletId): Flow { + return promoSettingsRepository.isReadyToShowRingPromo(userWalletId) + } + + suspend fun neverToShow() = promoSettingsRepository.setNeverToShowRingPromo() +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PromoSettingsRepository.kt b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PromoSettingsRepository.kt index 0e3946bb89..758763828a 100644 --- a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PromoSettingsRepository.kt +++ b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/PromoSettingsRepository.kt @@ -1,5 +1,6 @@ package com.tangem.domain.settings.repositories +import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow interface PromoSettingsRepository { @@ -14,4 +15,8 @@ interface PromoSettingsRepository { fun isReadyToShowWalletTravalaPromo(): Flow suspend fun setNeverToShowWalletTravalaPromo() + + fun isReadyToShowRingPromo(userWalletId: UserWalletId): Flow + + suspend fun setNeverToShowRingPromo() } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/InvalidatePendingTransactionsUseCase.kt b/domain/staking/src/main/java/com/tangem/domain/staking/InvalidatePendingTransactionsUseCase.kt index ca5a993891..6dd0f53745 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/InvalidatePendingTransactionsUseCase.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/InvalidatePendingTransactionsUseCase.kt @@ -9,6 +9,7 @@ import com.tangem.domain.staking.repositories.StakingErrorResolver import com.tangem.domain.staking.repositories.StakingPendingTransactionRepository import com.tangem.domain.wallets.models.UserWalletId import org.joda.time.DateTime +import java.math.BigDecimal import java.util.UUID class InvalidatePendingTransactionsUseCase( @@ -41,12 +42,13 @@ class InvalidatePendingTransactionsUseCase( newBalancesId: Int, pendingData: List>, ): Pair, List> { - val balances = realData.associateBy { Pair(it.groupId to it.type, it.amount to it.date) }.toMutableMap() + val balances = realData.associateBy { BalanceIdentity(it.groupId, it.type, it.amount, it.date) } + .toMutableMap() val transactionsToRemove = mutableListOf() pendingData.forEach { (pendingTransaction, balanceItem) -> - val key = Pair(balanceItem.groupId to balanceItem.type, balanceItem.amount to balanceItem.date) + val key = BalanceIdentity(balanceItem.groupId, balanceItem.type, balanceItem.amount, balanceItem.date) val oldBalancesId = pendingTransaction.balancesId when { @@ -59,21 +61,37 @@ class InvalidatePendingTransactionsUseCase( else -> { val groupId = UUID.randomUUID().toString() val now = DateTime.now() - balances[Pair(groupId to BalanceType.STAKED, pendingTransaction.amount to now)] = BalanceItem( - groupId = groupId, - type = pendingTransaction.type, - amount = pendingTransaction.amount, - rawCurrencyId = pendingTransaction.rawCurrencyId, - validatorAddress = pendingTransaction.validator?.address, - date = null, - pendingActions = emptyList(), - token = pendingTransaction.token, - isPending = true, - ) + balances[BalanceIdentity(groupId, BalanceType.STAKED, pendingTransaction.amount, now)] = + BalanceItem( + groupId = groupId, + type = pendingTransaction.type, + amount = pendingTransaction.amount, + rawCurrencyId = pendingTransaction.rawCurrencyId, + validatorAddress = pendingTransaction.validator?.address, + date = null, + pendingActions = emptyList(), + token = pendingTransaction.token, + isPending = true, + ) + + balances.entries.find { + it.key.type == BalanceType.STAKED && + it.key.amount == pendingTransaction.amount && + !it.value.isPending + } + ?.key + ?.let { balances.remove(it) } } } } return balances.values.toList() to transactionsToRemove } + + private data class BalanceIdentity( + val groupId: String, + val type: BalanceType, + val amount: BigDecimal, + val date: DateTime?, + ) } \ No newline at end of file diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt index 6e48ed4272..6242d8bbc2 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenSwapPromoAnalyticsEvent.kt @@ -39,5 +39,6 @@ sealed class TokenSwapPromoAnalyticsEvent( enum class ProgramName { Travala, OKX, + Ring, } } \ No newline at end of file diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt index 51ba0a57f9..3cd5eacc17 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/repository/PromoRepository.kt @@ -9,4 +9,6 @@ interface PromoRepository { suspend fun getTravalaPromoBanner(): PromoBanner? suspend fun getOkxPromoBanner(): PromoBanner? + + suspend fun getRingPromoBanner(): PromoBanner? } \ No newline at end of file diff --git a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt index 247f3c7605..975bac4246 100644 --- a/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt +++ b/domain/transaction/src/main/java/com/tangem/domain/transaction/TransactionRepository.kt @@ -1,9 +1,9 @@ package com.tangem.domain.transaction import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.CommonSigner import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.TransactionExtras +import com.tangem.blockchain.common.TransactionSigner import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionSendResult import com.tangem.blockchain.common.transaction.TransactionsSendResult @@ -54,14 +54,14 @@ interface TransactionRepository { suspend fun sendTransaction( txData: TransactionData, - signer: CommonSigner, + signer: TransactionSigner, userWalletId: UserWalletId, network: Network, ): com.tangem.blockchain.extensions.Result suspend fun sendMultipleTransactions( txsData: List, - signer: CommonSigner, + signer: TransactionSigner, userWalletId: UserWalletId, network: Network, ): com.tangem.blockchain.extensions.Result diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt index 003f9b9ff2..ff8f854078 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/repository/WalletsRepository.kt @@ -1,5 +1,6 @@ package com.tangem.domain.wallets.repository +import com.tangem.domain.wallets.models.UserWalletId import kotlinx.coroutines.flow.Flow interface WalletsRepository { @@ -9,4 +10,8 @@ interface WalletsRepository { fun shouldSaveUserWallets(): Flow suspend fun saveShouldSaveUserWallets(item: Boolean) + + suspend fun isWalletWithRing(userWalletId: UserWalletId): Boolean + + suspend fun setHasWalletsWithRing(userWalletId: UserWalletId) } \ No newline at end of file diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt index e47861902f..bf614cd4a1 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/DefaultSwapRepository.kt @@ -37,11 +37,10 @@ import timber.log.Timber import java.io.IOException import java.math.BigDecimal import java.util.UUID -import javax.inject.Inject import com.tangem.datasource.api.express.models.request.LeastTokenInfo as NetworkLeastTokenInfo @Suppress("LongParameterList", "LargeClass") -internal class DefaultSwapRepository @Inject constructor( +internal class DefaultSwapRepository( private val tangemExpressApi: TangemExpressApi, private val coroutineDispatcher: CoroutineDispatcherProvider, private val walletManagersFacade: WalletManagersFacade, @@ -186,6 +185,7 @@ internal class DefaultSwapRepository @Inject constructor( } override suspend fun findBestQuote( + userWalletId: UserWalletId, fromContractAddress: String, fromNetwork: String, toContractAddress: String, diff --git a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt index 0f47053aa3..46ebd1d768 100644 --- a/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt +++ b/features/swap/domain/api/src/main/java/com/tangem/feature/swap/domain/api/SwapRepository.kt @@ -18,6 +18,7 @@ interface SwapRepository { @Suppress("LongParameterList") suspend fun findBestQuote( + userWalletId: UserWalletId, fromContractAddress: String, fromNetwork: String, toContractAddress: String, diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index ad923ed16c..b77df21551 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -308,6 +308,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( isBalanceWithoutFeeEnough: Boolean, ): Pair { val maybeQuotes = repository.findBestQuote( + userWalletId = userWalletId, fromContractAddress = fromToken.currency.getContractAddress(), fromNetwork = fromToken.currency.network.backendId, toContractAddress = toToken.currency.getContractAddress(), @@ -1178,14 +1179,15 @@ internal class SwapInteractorImpl @AssistedInject constructor( } val quotes = repository.findBestQuote( + userWalletId = userWalletId, fromContractAddress = fromToken.getContractAddress(), fromNetwork = fromToken.network.backendId, toContractAddress = toToken.getContractAddress(), toNetwork = toToken.network.backendId, fromAmount = amountToRequest.toStringWithRightOffset(), fromDecimals = amount.decimals, - providerId = provider.providerId, toDecimals = toToken.decimals, + providerId = provider.providerId, rateType = RateType.FLOAT, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index 2686a1ec9d..fecbf47463 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -56,6 +56,10 @@ internal class WalletWarningsAnalyticsSender @Inject constructor( is WalletNotification.Warning.SomeNetworksUnreachable, is WalletNotification.Warning.NetworksUnreachable, -> null + is WalletNotification.RingPromo -> TokenSwapPromoAnalyticsEvent.NoticePromotionBanner( + source = AnalyticsParam.ScreensSources.Main, + programName = TokenSwapPromoAnalyticsEvent.ProgramName.Ring, + ) } } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt index 031c843c16..5ea90e12d4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt @@ -6,7 +6,7 @@ import com.tangem.domain.core.lce.Lce import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.promo.PromoBanner import com.tangem.domain.settings.IsReadyToShowRateAppUseCase -import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase +import com.tangem.domain.settings.ShouldShowRingPromoUseCase import com.tangem.domain.tokens.GetTokenListUseCase import com.tangem.domain.tokens.error.TokenListError import com.tangem.domain.tokens.model.CryptoCurrency @@ -33,7 +33,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( private val getTokenListUseCase: GetTokenListUseCase, private val isDemoCardUseCase: IsDemoCardUseCase, private val isReadyToShowRateAppUseCase: IsReadyToShowRateAppUseCase, - private val shouldShowSwapPromoWalletUseCase: ShouldShowSwapPromoWalletUseCase, + private val shouldShowRingPromoUseCase: ShouldShowRingPromoUseCase, private val promoRepository: PromoRepository, private val isNeedToBackupUseCase: IsNeedToBackupUseCase, private val backupValidator: BackupValidator, @@ -42,16 +42,16 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow> { val cardTypesResolver = userWallet.scanResponse.cardTypesResolver - val promoFlow = flow { emit(promoRepository.getOkxPromoBanner()) } + val promoFlow = flow { emit(promoRepository.getRingPromoBanner()) } return combine( flow = getTokenListUseCase.launch(userWallet.walletId), flow2 = isReadyToShowRateAppUseCase(), flow3 = isNeedToBackupUseCase(userWallet.walletId), - flow4 = shouldShowSwapPromoWalletUseCase(), + flow4 = shouldShowRingPromoUseCase(userWalletId = userWallet.walletId), flow5 = promoFlow, ) { maybeTokenList, isReadyToShowRating, isNeedToBackup, shouldShowPromo, promoBanner -> buildList { - addSwapPromoNotification(shouldShowPromo, promoBanner, clickIntents) + addRingPromoNotification(shouldShowPromo, promoBanner, clickIntents) addCriticalNotifications(userWallet, clickIntents) @@ -70,17 +70,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( } } - private fun MutableList.addSwapPromoNotification( + private fun MutableList.addRingPromoNotification( shouldShowPromo: Boolean, promoBanner: PromoBanner?, clickIntents: WalletClickIntents, ) { promoBanner ?: return - val promoNotification = WalletNotification.SwapPromo( - startDateTime = promoBanner.bannerState.timeline.start, - endDateTime = promoBanner.bannerState.timeline.end, - onCloseClick = clickIntents::onCloseSwapPromoClick, - ) + val promoNotification = WalletNotification.RingPromo(onCloseClick = clickIntents::onCloseRingPromoClick) addIf( element = promoNotification, condition = shouldShowPromo && promoBanner.isActive, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt index c878757dbc..2741cc56ca 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt @@ -194,4 +194,14 @@ sealed class WalletNotification(val config: NotificationConfig) { onCloseClick = onCloseClick, ), ) + + data class RingPromo(val onCloseClick: () -> Unit) : WalletNotification( + config = NotificationConfig( + title = resourceReference(id = R.string.ring_promo_title), + subtitle = resourceReference(id = R.string.ring_promo_text), + iconResId = R.drawable.img_card_with_ring, + backgroundResId = R.drawable.img_ring_promo_background, + onCloseClick = onCloseClick, + ), + ) } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt index 6ceb82e75c..55ca2d223b 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletCard.kt @@ -1,11 +1,12 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.common import android.content.res.Configuration -import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedContent import androidx.compose.animation.core.tween -import androidx.compose.foundation.Image +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.togetherWith import androidx.compose.foundation.LocalIndication import androidx.compose.foundation.background import androidx.compose.foundation.gestures.detectTapGestures @@ -25,11 +26,9 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalHapticFeedback -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -55,7 +54,7 @@ import com.tangem.feature.wallet.impl.R import com.tangem.feature.wallet.presentation.common.WalletPreviewData import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState -private const val HALF_OF_ITEM_WIDTH = 0.5 +// private const val HALF_OF_ITEM_WIDTH = 0.5 /** * Wallet card @@ -117,31 +116,33 @@ internal fun WalletCard(state: WalletCardState, isBalanceHidden: Boolean, modifi bottom.linkTo(anchor = parent.bottom, margin = contentVerticalMargin) if (additionalText != null) { - width = if (state.imageResId != null) { - end.linkTo(imageRef.start) - Dimension.fillToConstraints - } else { - Dimension.wrapContent - } + width = Dimension.wrapContent + // TODO: [REDACTED_JIRA] + // width = if (state.imageResId != null) { + // end.linkTo(imageRef.start) + // Dimension.fillToConstraints + // } else { + // Dimension.wrapContent + // } } }, ) + // TODO: [REDACTED_JIRA] // If balance has a large width then image must be hidden - val hasSpaceForImage by remember(key1 = balanceWidth, key2 = itemSize.width) { - mutableStateOf(value = balanceWidth < itemSize.width * HALF_OF_ITEM_WIDTH) - } - - if (hasSpaceForImage) { - Image( - id = state.imageResId, - modifier = Modifier.constrainAs(imageRef) { - end.linkTo(parent.end) - bottom.linkTo(parent.bottom) - height = Dimension.fillToConstraints - }, - ) - } + // val hasSpaceForImage by remember(key1 = balanceWidth, key2 = itemSize.width) { + // mutableStateOf(value = balanceWidth < itemSize.width * HALF_OF_ITEM_WIDTH) + // } + // if (hasSpaceForImage) { + // Image( + // id = state.imageResId, + // modifier = Modifier.constrainAs(imageRef) { + // end.linkTo(parent.end) + // bottom.linkTo(parent.bottom) + // height = Dimension.fillToConstraints + // }, + // ) + // } } } @@ -370,19 +371,19 @@ private fun LockedContent(modifier: Modifier = Modifier) { ) } -@Composable -private fun Image(@DrawableRes id: Int?, modifier: Modifier = Modifier) { - AnimatedVisibility(visible = id != null, modifier = modifier) { - val imageRes = id ?: return@AnimatedVisibility - - Image( - painter = painterResource(id = imageRes), - contentDescription = null, - modifier = Modifier.width(width = TangemTheme.dimens.size120), - contentScale = ContentScale.FillWidth, - ) - } -} +// @Composable +// private fun Image(@DrawableRes id: Int?, modifier: Modifier = Modifier) { +// AnimatedVisibility(visible = id != null, modifier = modifier) { +// val imageRes = id ?: return@AnimatedVisibility +// +// Image( +// painter = painterResource(id = imageRes), +// contentDescription = null, +// modifier = Modifier.width(width = TangemTheme.dimens.size120), +// contentScale = ContentScale.FillWidth, +// ) +// } +// } // region Preview diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt index b27ba3f5e5..39dbbb2618 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/common/WalletNotifications.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.lazy.items import androidx.compose.ui.Modifier import com.tangem.core.ui.components.notifications.Notification import com.tangem.core.ui.components.notifications.OkxPromoNotification +import com.tangem.core.ui.components.notifications.RingPromoNotification import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification import kotlinx.collections.immutable.ImmutableList @@ -33,6 +34,9 @@ internal fun LazyListScope.notifications(configs: ImmutableList { + RingPromoNotification(config = it.config, modifier = modifier.animateItemPlacement()) + } else -> { Notification( config = it.config, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt index a911c09913..e7386f4925 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/intents/WalletWarningsClickIntents.kt @@ -11,10 +11,7 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.redux.LegacyAction import com.tangem.domain.redux.ReduxStateHolder -import com.tangem.domain.settings.NeverToSuggestRateAppUseCase -import com.tangem.domain.settings.RemindToRateAppLaterUseCase -import com.tangem.domain.settings.ShouldShowSwapPromoWalletUseCase -import com.tangem.domain.settings.ShouldShowTravalaPromoWalletUseCase +import com.tangem.domain.settings.* import com.tangem.domain.tokens.FetchTokenListUseCase import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent @@ -62,6 +59,8 @@ internal interface WalletWarningsClickIntents { fun onCloseSwapPromoClick() + fun onCloseRingPromoClick() + fun onTravalaPromoClick(link: String?) fun onCloseTravalaPromoClick() @@ -86,6 +85,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( private val reduxStateHolder: ReduxStateHolder, private val dispatchers: CoroutineDispatcherProvider, private val shouldShowSwapPromoWalletUseCase: ShouldShowSwapPromoWalletUseCase, + private val shouldShowRingPromoUseCase: ShouldShowRingPromoUseCase, private val shouldShowTravalaPromoWalletUseCase: ShouldShowTravalaPromoWalletUseCase, private val getCardInfoUseCase: GetCardInfoUseCase, private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, @@ -242,6 +242,20 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor( } } + override fun onCloseRingPromoClick() { + analyticsEventHandler.send( + TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( + source = AnalyticsParam.ScreensSources.Main, + programName = TokenSwapPromoAnalyticsEvent.ProgramName.Ring, + action = TokenSwapPromoAnalyticsEvent.PromotionBannerClicked.BannerAction.Closed, + ), + ) + + viewModelScope.launch { + shouldShowRingPromoUseCase.neverToShow() + } + } + override fun onTravalaPromoClick(link: String?) { analyticsEventHandler.send( TokenSwapPromoAnalyticsEvent.PromotionBannerClicked( diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 22f0f9ac29..25ccff76f0 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -91,7 +91,7 @@ markdownComposeView = "0.5.4" # region Tangem tangemBlockchainSdk = "develop-817" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "develop-387" +tangemCardSdk = "develop-391" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem17" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ diff --git a/libs/auth/src/main/java/com/tangem/lib/auth/ExpressAuthProvider.kt b/libs/auth/src/main/java/com/tangem/lib/auth/ExpressAuthProvider.kt index 8582fd21ed..ebca655e53 100644 --- a/libs/auth/src/main/java/com/tangem/lib/auth/ExpressAuthProvider.kt +++ b/libs/auth/src/main/java/com/tangem/lib/auth/ExpressAuthProvider.kt @@ -5,4 +5,6 @@ interface ExpressAuthProvider { fun getUserId(): String fun getSessionId(): String + + fun getRefCode(): String } \ No newline at end of file diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/signer/TransactionSignerFactory.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/signer/TransactionSignerFactory.kt new file mode 100644 index 0000000000..da53a4d024 --- /dev/null +++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/signer/TransactionSignerFactory.kt @@ -0,0 +1,12 @@ +package com.tangem.blockchainsdk.signer + +import com.tangem.TangemSdk +import com.tangem.blockchain.common.TransactionSigner + +/** +[REDACTED_AUTHOR] + */ +interface TransactionSignerFactory { + + fun createTransactionSigner(cardId: String?, sdk: TangemSdk): TransactionSigner +} \ No newline at end of file