diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index ac3eeb6f5d..8f2af51f2d 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -14,6 +14,7 @@
+
diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
index e1dfdea4c1..f35a636601 100644
--- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
+++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt
@@ -13,7 +13,6 @@ sealed class Onboarding(
class Started : Onboarding("Onboarding", "Onboarding Started")
class Finished : Onboarding("Onboarding", "Onboarding Finished")
- data object OfflineAttestationFailed : Onboarding(category = "Onboarding", event = "Offline Attestation Failed")
sealed class CreateWallet(
event: String,
diff --git a/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt
index c80f34373b..9bdca56b66 100644
--- a/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt
+++ b/app/src/main/java/com/tangem/tap/common/pushes/TangemPushNotificationService.kt
@@ -38,7 +38,7 @@ internal class TangemPushNotificationService : FirebaseMessagingService() {
// TODO refactoring: [REDACTED_JIRA]
val intent = Intent(applicationContext, MainActivity::class.java)
- intent.putExtra(OnPushClickedIntentHandler.IS_OPENED_FROM_PUSH, true)
+ intent.putExtra(OnPushClickedIntentHandler.OPENED_FROM_GCM_PUSH, true)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(
/* context = */ this,
diff --git a/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
index 18882c44dd..df54352380 100644
--- a/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
+++ b/app/src/main/java/com/tangem/tap/common/ui/AddressInfoBottomSheetDialog.kt
@@ -67,7 +67,7 @@ internal class AddressInfoBottomSheetDialog(
val blockchain = stateDialog.currency.blockchain
tvReceiveMessage.text = tvReceiveMessage.getString(
id = R.string.address_qr_code_message_format,
- blockchain.fullName,
+ blockchain.getCoinName(),
blockchain.currency,
blockchain.fullName,
)
diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanCardProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanCardProcessor.kt
index a7592add78..216af3ca6d 100644
--- a/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanCardProcessor.kt
+++ b/app/src/main/java/com/tangem/tap/domain/scanCard/DefaultScanCardProcessor.kt
@@ -19,11 +19,13 @@ internal class DefaultScanCardProcessor(
override suspend fun scan(
cardId: String?,
allowsRequestAccessCodeFromRepository: Boolean,
+ analyticsSource: AnalyticsParam.ScreensSources,
): CompletionResult {
return if (isNewCardScanningEnabled) {
UseCaseScanProcessor.scan(cardId, allowsRequestAccessCodeFromRepository)
} else {
legacyScanProcessor.scan(
+ analyticsSource = analyticsSource,
cardId = cardId,
allowsRequestAccessCodeFromRepository = allowsRequestAccessCodeFromRepository,
)
diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt
index 0d0d13797e..27fa8ead9e 100644
--- a/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt
+++ b/app/src/main/java/com/tangem/tap/domain/scanCard/LegacyScanProcessor.kt
@@ -59,13 +59,14 @@ internal class LegacyScanProcessor @Inject constructor(
suspend fun scan(
cardId: String? = null,
allowsRequestAccessCodeFromRepository: Boolean = false,
+ analyticsSource: AnalyticsParam.ScreensSources,
): CompletionResult {
return tangemSdkManager.scanProduct(
cardId = cardId,
allowsRequestAccessCodeFromRepository = allowsRequestAccessCodeFromRepository,
)
.doOnFailure { error ->
- onScanFailure(error = error, onFailure = {}, onCancel = {})
+ onScanFailure(analyticsSource = analyticsSource, error = error, onFailure = {}, onCancel = {})
}
}
@@ -92,6 +93,7 @@ internal class LegacyScanProcessor @Inject constructor(
result
.doOnFailure { error ->
onScanFailure(
+ analyticsSource = analyticsSource,
error = error,
onFailure = onFailure,
onCancel = {
@@ -162,12 +164,17 @@ internal class LegacyScanProcessor @Inject constructor(
}
private suspend inline fun onScanFailure(
+ analyticsSource: AnalyticsParam.ScreensSources,
error: TangemError,
crossinline onFailure: suspend (TangemError) -> Unit,
crossinline onCancel: () -> Unit,
) {
if (error is TangemSdkError.CardVerificationFailed) {
- analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed)
+ analyticsEventHandler.send(
+ event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed(
+ analyticsSource,
+ ),
+ )
val resource = error.localizedDescriptionRes()
val resId = resource.resId ?: R.string.common_unknown_error
diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt
index 8ede05a98a..bbf156324b 100644
--- a/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt
+++ b/app/src/main/java/com/tangem/tap/features/details/ui/cardsettings/CardSettingsViewModel.kt
@@ -66,7 +66,10 @@ internal class CardSettingsViewModel @Inject constructor(
)
private fun scanCard() = viewModelScope.launch {
- scanCardProcessor.scan(allowsRequestAccessCodeFromRepository = true)
+ scanCardProcessor.scan(
+ analyticsSource = com.tangem.core.analytics.models.AnalyticsParam.ScreensSources.Settings,
+ allowsRequestAccessCodeFromRepository = true,
+ )
.doOnSuccess { scanResponse ->
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse).build()
if (userWalletId == scannedUserWalletId || scannedUserWalletId == null) {
diff --git a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/OnPushClickedIntentHandler.kt b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/OnPushClickedIntentHandler.kt
index e21d25ea54..e6b36001d8 100644
--- a/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/OnPushClickedIntentHandler.kt
+++ b/app/src/main/java/com/tangem/tap/features/intentHandler/handlers/OnPushClickedIntentHandler.kt
@@ -8,7 +8,7 @@ import com.tangem.tap.features.intentHandler.IntentHandler
internal class OnPushClickedIntentHandler(val analyticsEventHandler: AnalyticsEventHandler) : IntentHandler {
override fun handleIntent(intent: Intent?, isFromForeground: Boolean): Boolean {
- val fromPush = intent?.extras?.getBoolean(IS_OPENED_FROM_PUSH) ?: false
+ val fromPush = intent?.extras?.containsKey(OPENED_FROM_GCM_PUSH) ?: false
return if (fromPush) {
analyticsEventHandler.send(Push.PushNotificationOpened)
@@ -19,6 +19,6 @@ internal class OnPushClickedIntentHandler(val analyticsEventHandler: AnalyticsEv
}
companion object {
- const val IS_OPENED_FROM_PUSH = "IS_OPENED_FROM_PUSH"
+ const val OPENED_FROM_GCM_PUSH = "google.sent_time" // every bundle from FCM contains this key
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt
index 7c1adf4a81..b1940958e7 100644
--- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt
+++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt
@@ -99,7 +99,7 @@ object OnboardingHelper {
}
}
- fun saveWallet(
+ suspend fun saveWallet(
alreadyCreatedWallet: UserWallet?,
scanResponse: ScanResponse,
accessCode: String? = null,
@@ -107,46 +107,42 @@ object OnboardingHelper {
hasBackupError: Boolean = false,
) {
Analytics.setContext(scanResponse)
- scope.launch {
- val settingsRepository = store.inject(DaggerGraphState::settingsRepository)
- when {
- // When should save user wallets, then save card without navigate to save wallet screen
- store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
- store.dispatchWithMain(
- SaveWalletAction.ProvideBackupInfo(
- scanResponse = scanResponse,
- accessCode = accessCode,
- backupCardsIds = backupCardsIds?.toSet(),
- ),
- )
+ val settingsRepository = store.inject(DaggerGraphState::settingsRepository)
+ when {
+ // When should save user wallets, then save card without navigate to save wallet screen
+ store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> {
+ store.dispatchWithMain(
+ SaveWalletAction.ProvideBackupInfo(
+ scanResponse = scanResponse,
+ accessCode = accessCode,
+ backupCardsIds = backupCardsIds?.toSet(),
+ ),
+ )
- store.dispatchWithMain(
- SaveWalletAction.SaveWalletAfterBackup(
- hasBackupError = hasBackupError,
- shouldNavigateToWallet = false,
- ),
- )
- }
- // When should not save user wallets but device has biometry and save wallet screen has not been shown,
- // then open save wallet screen
- tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen() -> {
- proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
-
- delay(timeMillis = 1_200)
-
- store.dispatchOnMain(
- SaveWalletAction.ProvideBackupInfo(
- scanResponse = scanResponse,
- accessCode = accessCode,
- backupCardsIds = backupCardsIds?.toSet(),
- ),
- )
- }
- // If device has no biometry and save wallet screen has been shown, then go through old scenario
- else -> {
- proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
- }
+ store.dispatchWithMain(
+ SaveWalletAction.SaveWalletAfterBackup(
+ hasBackupError = hasBackupError,
+ shouldNavigateToWallet = false,
+ ),
+ )
}
+ // When should not save user wallets but device has biometry and save wallet screen has not been shown,
+ // then open save wallet screen
+ tangemSdkManager.checkCanUseBiometry() && settingsRepository.shouldShowSaveUserWalletScreen() -> {
+ proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
+
+ delay(timeMillis = 1_200)
+
+ store.dispatchWithMain(
+ SaveWalletAction.ProvideBackupInfo(
+ scanResponse = scanResponse,
+ accessCode = accessCode,
+ backupCardsIds = backupCardsIds?.toSet(),
+ ),
+ )
+ }
+ // If device has no biometry and save wallet screen has been shown, then go through old scenario
+ else -> proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError, alreadyCreatedWallet)
}
}
diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt
index 78a0248326..4b8ab7545a 100644
--- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt
+++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt
@@ -7,6 +7,7 @@ import com.tangem.common.extensions.guard
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.utils.popTo
import com.tangem.core.analytics.Analytics
+import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.ui.R
import com.tangem.core.ui.extensions.resourceReference
@@ -356,7 +357,9 @@ private fun handle(action: Action, dispatch: DispatchFunction) {
private fun showCardVerificationFailedDialog(error: TangemError) {
if (error is TangemSdkError.CardVerificationFailed) {
- Analytics.send(event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed)
+ Analytics.send(
+ event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed(AnalyticsParam.ScreensSources.Backup),
+ )
val resource = error.localizedDescriptionRes()
val resId = resource.resId ?: R.string.common_unknown_error
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 b87183595a..df9ee2e6b7 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
@@ -4,7 +4,6 @@ import android.net.Uri
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.common.CompletionResult
import com.tangem.common.card.Card
-import com.tangem.common.core.TangemError
import com.tangem.common.core.TangemSdkError
import com.tangem.common.extensions.ifNotNull
import com.tangem.common.extensions.toHexString
@@ -12,6 +11,7 @@ import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.services.Result
import com.tangem.core.analytics.Analytics
+import com.tangem.core.analytics.models.AnalyticsParam.ScreensSources
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.toWrappedList
@@ -43,7 +43,6 @@ import com.tangem.tap.common.extensions.*
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.features.demo.DemoHelper
-import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.onboarding.OnboardingDialog
import com.tangem.tap.features.onboarding.OnboardingHelper
import com.tangem.tap.proxy.redux.DaggerGraphState
@@ -52,7 +51,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.rekotlin.Action
import org.rekotlin.Middleware
-import timber.log.Timber
object OnboardingWalletMiddleware {
val handler = onboardingWalletMiddleware
@@ -203,7 +201,7 @@ private fun handleWalletAction(action: Action) {
}
}
-private fun handleFinishBackup(scanResponse: ScanResponse, userWallet: UserWallet? = null) {
+private suspend fun handleFinishBackup(scanResponse: ScanResponse, userWallet: UserWallet? = null) {
val backupState = store.state.onboardingWalletState.backupState
val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState)
@@ -234,31 +232,14 @@ private fun navigateToWalletScreen() {
}
}
-private suspend fun readCard(onSuccess: suspend (ScanResponse) -> Unit, onFailure: (TangemError) -> Unit) {
+private suspend fun readCard(): CompletionResult {
val shouldSaveAccessCodes = store.inject(DaggerGraphState::settingsRepository).shouldSaveAccessCodes()
store.inject(DaggerGraphState::cardSdkConfigRepository).setAccessCodeRequestPolicy(
isBiometricsRequestPolicy = shouldSaveAccessCodes,
)
- store.inject(DaggerGraphState::scanCardProcessor).scan(
- analyticsSource = com.tangem.core.analytics.models.AnalyticsParam.ScreensSources.Intro,
- onProgressStateChange = { showProgress ->
- if (showProgress) {
- store.dispatch(HomeAction.ScanInProgress(scanInProgress = true))
- } else {
- delay(HIDE_PROGRESS_DELAY)
- store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
- }
- },
- onFailure = {
- Timber.e(it, "Unable to scan card")
- delay(HIDE_PROGRESS_DELAY)
- store.dispatch(HomeAction.ScanInProgress(scanInProgress = false))
- onFailure(it)
- },
- onSuccess = onSuccess,
- )
+ return store.inject(DaggerGraphState::scanCardProcessor).scan(analyticsSource = ScreensSources.Intro)
}
private suspend fun loadArtworkForCard(cardId: String, cardPublicKey: ByteArray, defaultArtwork: Uri?): Uri {
@@ -476,7 +457,11 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
when (val error = result.error) {
is TangemSdkError.CardVerificationFailed -> {
- Analytics.send(event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed)
+ Analytics.send(
+ event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed(
+ ScreensSources.Backup,
+ ),
+ )
val resource = error.localizedDescriptionRes()
val resId = resource.resId ?: com.tangem.core.ui.R.string.common_unknown_error
@@ -656,23 +641,22 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
Analytics.send(Onboarding.Finished())
scope.launch {
- store.state.globalState.onboardingState.onboardingManager?.finishActivation(
- cardIds = gatherCardIds(backupState, card),
- )
- }
- if (scanResponse == null) {
- scope.launch {
- readCard(
- onSuccess = { newScanResponse ->
- handleFinishBackup(newScanResponse)
- },
- onFailure = {
- store.dispatchNavigationAction(AppRouter::pop)
- },
+ launch {
+ store.state.globalState.onboardingState.onboardingManager?.finishActivation(
+ cardIds = gatherCardIds(backupState, card),
)
}
- } else {
- handleFinishBackup(scanResponse)
+
+ with(scanResponse) {
+ if (this == null) {
+ when (val result = readCard()) {
+ is CompletionResult.Success -> handleFinishBackup(result.data)
+ is CompletionResult.Failure -> store.dispatchNavigationAction(AppRouter::pop)
+ }
+ } else {
+ handleFinishBackup(scanResponse = this)
+ }
+ }
}
}
is BackupAction.FinishBackup -> {
@@ -688,40 +672,39 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
scanResponse = requireNotNull(value = scanResponse, lazyMessage = { "ScanResponse is null" }),
backupState = backupState,
)
-
- val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
- when (backupState.startedSource) {
- BackupStartedSource.Onboarding -> saveWallet(
- userWalletsListManager = userWalletsListManager,
- userWallet = userWallet,
- scanResponse = scanResponse,
- backupState = backupState,
- )
- BackupStartedSource.CreateBackup -> updateWallet(
- userWalletsListManager = userWalletsListManager,
- userWallet = userWallet,
- backupState = backupState,
- )
- }
} else {
delay(HIDE_PROGRESS_DELAY)
- readCard(
- onSuccess = { newScanResponse ->
- scanResponse = newScanResponse
- userWallet = createUserWallet(newScanResponse, backupState)
- },
- onFailure = {
+ when (val result = readCard()) {
+ is CompletionResult.Failure -> {
store.dispatchNavigationAction(AppRouter::pop)
- },
+ return@launch
+ }
+ is CompletionResult.Success -> {
+ scanResponse = result.data
+ userWallet = createUserWallet(scanResponse = result.data, backupState = backupState)
+ }
+ }
+ }
+
+ val userWalletsListManager = store.inject(DaggerGraphState::generalUserWalletsListManager)
+ when (backupState.startedSource) {
+ BackupStartedSource.Onboarding -> saveWallet(
+ userWalletsListManager = userWalletsListManager,
+ userWallet = userWallet,
+ scanResponse = scanResponse,
+ backupState = backupState,
+ )
+ BackupStartedSource.CreateBackup -> updateWallet(
+ userWalletsListManager = userWalletsListManager,
+ userWallet = userWallet,
+ backupState = backupState,
)
}
scope.launch {
- userWallet?.let {
- if (it.scanResponse.cardTypesResolver.isWallet2() && it.isImported) {
- store.inject(DaggerGraphState::walletsRepository).markWallet2WasCreated(it.walletId)
- }
+ if (userWallet.scanResponse.cardTypesResolver.isWallet2() && userWallet.isImported) {
+ store.inject(DaggerGraphState::walletsRepository).markWallet2WasCreated(userWallet.walletId)
}
}
@@ -736,7 +719,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
// All cardIds may already be activated if the backup was skipped before.
if (notActivatedCardIds.isEmpty()) {
delay(1000)
- store.dispatchWithMain(BackupAction.BackupFinished(userWallet?.walletId))
+ store.dispatchWithMain(BackupAction.BackupFinished(userWallet.walletId))
return@launch
}
@@ -744,8 +727,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
store.state.globalState.onboardingState.onboardingManager?.finishActivation(notActivatedCardIds)
handleFinishBackup(requireNotNull(scanResponse), userWallet)
- delay(1000)
- store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet?.walletId))
+ store.dispatchWithMain(BackupAction.BackupFinished(userWalletId = userWallet.walletId))
}
}
diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt
index 2f2e54876b..dceee7e356 100644
--- a/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt
+++ b/app/src/test/kotlin/com/tangem/tap/domain/card/CryptoCurrenciesMocks.kt
@@ -48,7 +48,7 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) {
val network = Network(
id = Network.ID(blockchain.id),
backendId = blockchain.toNetworkId(),
- name = blockchain.getNetworkName(),
+ name = blockchain.fullName,
isTestnet = blockchain.isTestnet(),
derivationPath = getNetworkDerivationPath(
blockchain,
@@ -76,7 +76,7 @@ internal class CryptoCurrenciesMocks(private val scanResponse: ScanResponse) {
network = Network(
id = Network.ID(value = blockchain.id),
backendId = "NEVER-MIND",
- name = blockchain.getNetworkName(),
+ name = blockchain.fullName,
currencySymbol = "NEVER-MIND",
derivationPath = Network.DerivationPath.Custom(
value = derivationBlockchain.derivationPath(
diff --git a/ci_resources/Dockerfile.android b/ci_resources/Dockerfile.android
new file mode 100644
index 0000000000..4573a0972d
--- /dev/null
+++ b/ci_resources/Dockerfile.android
@@ -0,0 +1,50 @@
+FROM ubuntu:24.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+ENV ANDROID_HOME=/opt/android-sdk
+ENV BUNDLE_PATH=vendor/bundle
+ENV PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/34.0.0:$BUNDLE_PATH/bin
+ENV LC_ALL=en_US.UTF-8
+ENV LANG=en_US.UTF-8
+
+RUN apt-get update && apt-get install -y \
+ openjdk-17-jdk \
+ wget \
+ unzip \
+ curl \
+ git \
+ ruby \
+ ruby-dev \
+ build-essential \
+ && apt-get clean
+
+RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
+ chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
+ echo "deb [signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list && \
+ apt-get update && apt-get install -y gh && \
+ apt-get clean
+
+RUN mkdir -p $ANDROID_HOME/cmdline-tools/latest && \
+ wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -O /tmp/cmdline-tools.zip && \
+ unzip /tmp/cmdline-tools.zip -d $ANDROID_HOME/cmdline-tools/latest && \
+ mv $ANDROID_HOME/cmdline-tools/latest/cmdline-tools/* $ANDROID_HOME/cmdline-tools/latest/ && \
+ rm -rf $ANDROID_HOME/cmdline-tools/latest/cmdline-tools && \
+ rm -f /tmp/cmdline-tools.zip && \
+ yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses && \
+ $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "platform-tools" "platforms;android-31" "platforms;android-34" "build-tools;34.0.0"
+
+RUN wget https://github.com/lzhiyong/android-sdk-tools/releases/download/34.0.3/android-sdk-tools-static-aarch64.zip -O /tmp/android-sdk-tools-static-aarch64.zip && \
+ unzip /tmp/android-sdk-tools-static-aarch64.zip -d /tmp/android-sdk-tools-static-arm && \
+ cp -r /tmp/android-sdk-tools-static-arm/build-tools/* $ANDROID_HOME/build-tools/34.0.0/ && \
+ rm -rf /tmp/android-sdk-tools-static-arm /tmp/android-sdk-tools-static-aarch64.zip
+
+RUN gem install bundler:2.5.23
+RUN gem install fastlane -v 2.211.0 -N -V
+RUN gem install fastlane-plugin-firebase_app_distribution -v 0.9.1 -N -V
+
+COPY ../Gemfile Gemfile.lock ./
+RUN bundle install --jobs=4 --retry=3 --verbose
+
+RUN bundle exec fastlane -v
+
+CMD ["bash"]
diff --git a/ci_resources/Dockerfile.lightweight b/ci_resources/Dockerfile.lightweight
new file mode 100644
index 0000000000..62c29262d9
--- /dev/null
+++ b/ci_resources/Dockerfile.lightweight
@@ -0,0 +1,19 @@
+FROM ubuntu:24.04
+
+RUN apt-get update && apt-get install -y \
+ curl \
+ git \
+ && apt-get clean
+
+RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \
+ chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \
+ echo "deb [signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list && \
+ apt-get update && apt-get install -y gh && \
+ apt-get clean
+
+RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && \
+ apt-get install -y git-lfs && \
+ git lfs install && \
+ apt-get clean
+
+CMD ["bash"]
diff --git a/ci_resources/find-latest-pre-release-branch.sh b/ci_resources/find-latest-pre-release-branch.sh
new file mode 100755
index 0000000000..653cbdd467
--- /dev/null
+++ b/ci_resources/find-latest-pre-release-branch.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+set -eo pipefail
+
+# Input args
+if [ -z "$1" ]; then
+ echo "Error: No base branch argument provided or empty string given."
+ echo "Usage: $0 "
+ exit 1
+fi
+base_branch=$1
+
+# Initialize variables to store the latest release branch and merge base
+latest_branch=""
+latest_merge_base=""
+
+# Source refs to find branches from
+local_refs="refs/heads/releases/*" # For debug and development
+remote_refs=$(git for-each-ref --sort=-committerdate --format="%(refname:short)" refs/remotes/origin/ | grep -E "origin/[a-zA-Z0-9._-]+_pre_release$")
+
+# Iterate over all remote release branches sorted by commit date (most recent first)
+for branch in $remote_refs; do
+ # Find the common ancestor (merge base) between the base branch and the current branch
+ merge_base=$(git merge-base "$base_branch" "$branch")
+
+ echo "Merge base for branches '$branch' and '$base_branch' is '$merge_base'"
+
+ # Update the latest branch and merge base if the current merge base is a descendant of the latest merge base
+ if [ -z "$latest_merge_base" ] || git merge-base --is-ancestor "$latest_merge_base" "$merge_base"; then
+ latest_branch="$branch"
+ latest_merge_base="$merge_base"
+ fi
+done
+
+echo "Latest branch: $latest_branch"
+echo "Latest merge base: $latest_merge_base"
+
+
+# Output validation
+if [ -z "$latest_branch" ]; then
+ echo "Error: Can't find the latest 'pre_release' branch for the base branch '$base_branch'"
+ exit 2
+fi
+
+# Stripping 'origin/' prefix if needed
+latest_branch="${latest_branch#origin/}"
+
+echo "$latest_branch" > "find-latest-pre-release-branch.output"
+echo "Latest 'pre_release' branch created from '$base_branch' or its ancestor: '$latest_branch'"
diff --git a/ci_resources/x86_64_libs/ld-linux-x86-64.so.2 b/ci_resources/x86_64_libs/ld-linux-x86-64.so.2
deleted file mode 100755
index 8ef4df1a3d..0000000000
Binary files a/ci_resources/x86_64_libs/ld-linux-x86-64.so.2 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/libc.so.6 b/ci_resources/x86_64_libs/libc.so.6
deleted file mode 100755
index 4b600449a0..0000000000
Binary files a/ci_resources/x86_64_libs/libc.so.6 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/libdl.so.2 b/ci_resources/x86_64_libs/libdl.so.2
deleted file mode 100644
index 2862f8ef7e..0000000000
Binary files a/ci_resources/x86_64_libs/libdl.so.2 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/libgcc_s.so.1 b/ci_resources/x86_64_libs/libgcc_s.so.1
deleted file mode 100644
index 0e7b8a5939..0000000000
Binary files a/ci_resources/x86_64_libs/libgcc_s.so.1 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/libm.so.6 b/ci_resources/x86_64_libs/libm.so.6
deleted file mode 100644
index 7a473b15f3..0000000000
Binary files a/ci_resources/x86_64_libs/libm.so.6 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/libpthread.so.0 b/ci_resources/x86_64_libs/libpthread.so.0
deleted file mode 100644
index 3e09ebef74..0000000000
Binary files a/ci_resources/x86_64_libs/libpthread.so.0 and /dev/null differ
diff --git a/ci_resources/x86_64_libs/librt.so.1 b/ci_resources/x86_64_libs/librt.so.1
deleted file mode 100644
index 8edf9c4312..0000000000
Binary files a/ci_resources/x86_64_libs/librt.so.1 and /dev/null differ
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 723451acf5..6e4b6e4a13 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
@@ -79,6 +79,8 @@ sealed class AnalyticsParam {
data object Buy : ScreensSources("Buy")
data object Swap : ScreensSources("Swap")
data object Sell : ScreensSources("Sell")
+ data object Backup : ScreensSources("Backup")
+ data object Onboarding : ScreensSources("Onboarding")
}
sealed class TxSentFrom(val value: String) {
diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/OnboardingAnalyticsEvent.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/OnboardingAnalyticsEvent.kt
index 454bdc1ab7..f60f3b53fe 100644
--- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/OnboardingAnalyticsEvent.kt
+++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/OnboardingAnalyticsEvent.kt
@@ -1,6 +1,7 @@
package com.tangem.core.analytics.models.event
import com.tangem.core.analytics.models.AnalyticsEvent
+import com.tangem.core.analytics.models.AnalyticsParam
sealed class OnboardingAnalyticsEvent(
category: String,
@@ -11,8 +12,13 @@ sealed class OnboardingAnalyticsEvent(
sealed class Onboarding(
event: String,
params: Map = mapOf(),
- ) : OnboardingAnalyticsEvent(category = "Onboarding", event = event, params = params) {
+ ) : OnboardingAnalyticsEvent(category = "Error", event = event, params = params) {
- data object OfflineAttestationFailed : Onboarding(event = "Offline Attestation Failed")
+ data class OfflineAttestationFailed(
+ val source: AnalyticsParam.ScreensSources,
+ ) : Onboarding(
+ event = "Offline Attestation Failed",
+ params = mapOf(AnalyticsParam.SOURCE to source.value),
+ )
}
}
\ No newline at end of file
diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml
index 2f5c61bad2..8a48bdcc9f 100644
--- a/core/res/src/main/res/values-de/strings.xml
+++ b/core/res/src/main/res/values-de/strings.xml
@@ -87,6 +87,8 @@
Nicht genug ADAAkzeptierenZugang verweigert
+ Zum Portfolio hinzufügen
+ Token hinzufügenAlleErlaubenAnalysen
@@ -105,7 +107,7 @@
ÄndernAktion wählenBeanspruchen
- Stakingbelohnungen beanstpruchen
+ Stakingbelohnungen beanspruchenSchließenBestätigenWeiter
@@ -197,7 +199,7 @@
Ich versteheEs ist ein Fehler aufgetreten. Bitte versuche es erneut.Nicht erreichbar
- staking beenden
+ Staking beendenwochemitJa
@@ -312,6 +314,9 @@
Gekauft %sKauf %sKauf %s…
+ Diese Transaktion ausblenden
+ Sobald dieser Bildschirm ausgeblendet wurde, kann er nicht mehr aufgerufen werden.
+ Bist Du sicher, dass Du die Transaktionsdetails ausblenden willst?Keine Token gefunden. Bitte versuche eine andere AnfrageID: %sTransaktions-ID kopiert
@@ -338,6 +343,8 @@
UnbegrenztKarte oder Ring bestellenKarte oder Ring scannen
+ An %s
+ In %sDiese Informationen wurden mithilfe von KI generiert.\nTippe hier, wenn Du Fehler finden.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.
@@ -654,7 +661,7 @@
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!
+ Jetzt mit 0 % Gebühren tauschen!Melde dich bei der App an und überprüfe dein Guthaben, ohne die Karte oder Ring zu scannenZugriff auf die AppNutzung biometrischer Daten zulassen
@@ -786,6 +793,8 @@
MigrierenNatives StakingDerzeit sind keine aktiven Validatoren für das Staking verfügbar. Bitte versuchen Sie es später erneut.
+ Beim Staking im Cardano Netzwerk wird das gesamte Guthaben genutzt. Zusätzlich werden 2 ADA reserviert und nach dem Unstaking zurückgegeben. Deine ADA sind während des Stakings nicht gesperrt.
+ Einzelheiten zum ADA-StakingVerdiente Belohnungen werden an Deine Wallet gesendet und stehen Dir sofort zur VerfügungStake sicher und verdienen BelohnungenSicher staken und tägliche Belohnungen verdienen.
@@ -799,6 +808,8 @@
Verdiene Staking-BelohnungenDein verbleibender Stakingbetrag ist zu niedrig, um den Einsatz aufzuheben. Du musst mehr Staken, um den Mindestbetrag zum Aufheben des Einsatzes zu erreichen.Niedriges Stakingguthaben
+ Für erneutes Staking sind mindestens %1$s %2$s erforderlich. Bitte lade Dein Guthaben auf.
+ Nicht genug %sAufgrund von Netzwerkproblemen ist Staking derzeit nicht verfügbar. Bitte versuche es später erneut.Beim Staking im %1$s -Netzwerk mit einem neuen Validator werden alle zuvor eingesetzten Kryptos automatisch an diesen Validator übertragenReinvestiert Deine verdienten Prämien in Deinen Einsatzbetrag und erhöht so den potenziellen Gewinn.
@@ -806,7 +817,7 @@
Du bist dabei, Dein gesamtes Guthaben zu staken. Wir empfehlen, einen kleinen Betrag übrig zu lassen, um die Netzwerkgebühren für die Aufhebung des Stakes oder das Einfordern von Prämien abzudecken.Entsperre dein Geld, um es aus dem Staking-Prozess abzuheben. Das Freischalten nimmt %s.Nach Ablauf der 21-tägigen Bindungsfrist kannst Du über Dein Guthaben verfügen. Die Prämie wird zusammen mit dem ungestaketen Guthaben abgehoben.
- Deine Assets steht Dir nach Ablauf der Frist für die Aufhebung der Bindung %s zur Verfügung.
+ Deine Assets stehen Dir nach Ablauf der Frist für die Aufhebung der Bindung %s zur Verfügung.Du kannst Dein Guthaben jetzt abheben. Es steht Dir sofort zur Verfügung.Wenn du im Tron-Netzwerk mit einem neuen Validator stakest, werden alle zuvor eingesetzten Assets automatisch an diesen Validator übertragen.Vorbereitung
@@ -838,7 +849,7 @@
Tippe zum Entsperren oder AbstimmenZum abheben antippenStake %s
- Staking beenden%s
+ Staking beenden %sDie Transaktion wird bearbeitet! Derzeit findet eine Validierung in der Blockchain statt. Dies kann einige Minuten dauern.Lösen der BindungenGelocktes unlocken
@@ -912,6 +923,7 @@
Tausche diesen Token gegen einen anderen zu %1$s Servicegebühren von Februar %2$s-%3$s.Tausche mit Changelly, %s GebührenJetzt tauschen
+ Hot Krypto 🔥Nicht verfügbar zum KaufNicht zum Verkauf verfügbarNicht verfügbar für Tausch von %s
@@ -945,7 +957,7 @@
Sei der Erste, der von neuen Aktionen erfährtMöchtest du Push-Benachrichtigungen verwenden?Neues Wallet hinzufügen
- Möchtest du diese Wallet wirklich löschen?
+ Möchtest Du diese Wallet wirklich entfernen?Es ist ein Fehler aufgetreten, bitte scanne deine Karte oder Ring, um sich anzumeldenDieses Wallet wurde bereits gespeichert, du kannst ein weiteres hinzufügenDie Wallet mit dem Namen %s existiert bereits
@@ -955,7 +967,7 @@
Alle mit %s freischaltenBlockchain ist nicht erreichbar. Versuche es später nochmalKarte oder Ring scannen
- Diese Wallet wurde bereits früher aktiviert.\nWenn es nicht von Dir durchgeführt wurde, wende Dich bitte an den Support.\nTangem verkauft niemals Wallets zusammen mit dem vorgenerierten Zugangscode.
+ Dieses Wallet wurde bereits früher aktiviert. \n Wenn dies nicht von Dir durchgeführt wurde, wende Dich bitte an den Support. \n Tangem verkauft niemals Wallets zusammen mit vorgenerierten Zugangscodes.Aufforderung zum Signieren einer Nachricht. \n\n %sDapp %1$s, mit der Bitte um\nBNB-Transaktion zu unterzeichnen.\n\n%2$sHandelsauftrag für %1$s\n Preis: %2$s\n Zu erhaltender Betrag: %3$s\n Zu zahlender Betrag: %4$s
@@ -993,7 +1005,7 @@
%s NetzwerkDie Adresse wurde erfolgreich kopiertKeine Internetverbindung
- Jetzt mit 10 %% Rabatt kaufen
+ Jetzt mit 10 % Rabatt kaufenGreife auf 13.000+ Kryptowährungen zu. Kaufe, verkaufe, tausche und stake Sie mit einem einzigen Fingertipp.\nVerbinde bis zu drei Karten für ein Backup.Entdecke die Tangem WalletWallet-Einstellungen
@@ -1044,6 +1056,7 @@
Bist Du sicher, dass Du die Transaktion stornieren willst? Du kannst die Transaktion nicht erneut starten.Deine Transaktion mit einem Betrag von %1$s %2$s wurde nicht abgeschlossen. Du kannst versuchen, diese erneut abzuschließen.Du hast eine nicht abgeschlossene Transaktion
+ Letzte Aktualisierung war %sAuf dieser Karte oder Ring sind nur noch %s Unterschriften übrig. Du musst dein gesamtes Guthaben abheben.Geringe Anzahl von UnterschriftenToken in verschiedenen Netzwerken können unterschiedliche Adressen haben. Überprüfe bei der Überweisung noch einmal, ob deine Adresse mit der des Netzwerks übereinstimmt.
@@ -1067,7 +1080,7 @@
Netzmietgebühr erforderlichVielen Dank! Alles erledigt! Keine weiteren Maßnahmen erforderlich.Sie werden jetzt auf die offizielle Tangem-Website weitergeleitet. Bitte lesen und befolgen Sie dort die Anweisungen.
- Haben Sie jemals das Support-Team von Tangem direkt über diese Anwendung kontaktiert?
+ Hast Du das Tangem-Supportteam schon einmal direkt über diese Anwendung kontaktiert?Verpflichtendes Sicherheitsupdate%1$s ist ein Vermögenswert im %2$s Netzwerk. Um eine %3$s Transaktion durchzuführen, musst du etwas %4$s (%5$s) einzahlen, um die Netzwerkgebühr zu decken.Unzureichende %1$s zur Deckung der Netzgebühr
@@ -1076,6 +1089,7 @@
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.Wischen Sie nach unten, um zu aktualisieren, oder versuchen Sie es später erneut.Einige Netzwerke sind nicht erreichbar
+ Einige Token-Guthaben konnten nicht aktualisiert werdenDies ist eine Testnet-Karte. Sie kann keine Transaktionen verarbeiten und sollte nur zu Test- und Entwicklungszwecken verwendet werden.Nur für TestzweckeVerwerfen
diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml
index 17a3e7c35f..5bd7fecb44 100644
--- a/core/res/src/main/res/values-es/strings.xml
+++ b/core/res/src/main/res/values-es/strings.xml
@@ -1,6 +1,6 @@
- ¿No encuentra el token en su billetera? Consulte los mercados para encontrarlo y añadirlo a la compra
+ ¿No encuentra el token en su billetera? Consulte la sección de Mercados para encontrarlo y añadirlo a la compra¿No encuentra el token en su billetera? Consulte los mercados para encontrarlo y añadirlo a la ventaVenderEsto puede tardar unos segundos. Inténtelo de nuevo más tarde.
@@ -28,8 +28,8 @@
Razón: %sNo se puede completar una transacciónEl seleccionado no admite la red %1$s
- Para activar el %1$s cifrado criptográfico de la blockchain, necesitarás reiniciar la billetera a los ajustes de fábrica. Por favor, retire sus fondos antes de hacerlo para asegurarte de no perderlos, y luego complete el proceso de reinicio. El acceso a la billetera actual no será posible después del reinicio.
- Esta tarjeta no admite %1$s tokens de red debido a una limitación del firmware.
+ Para activar el %1$s cifrado criptográfico de la blockchain, necesitarás reiniciar la billetera a los ajustes de fábrica. Por favor, retire sus fondos antes de hacerlo para asegurarse no perderlos, y luego complete el proceso de reinicio. El acceso a la billetera actual no será posible después del reinicio.
+ Esta tarjeta no admite tokens en la red %1$s debido a una limitación del firmware.¿Tiene dificultades para escanear su tarjeta/anillo?Esta tarjeta no está diseñada para funcionar con TangemTarifa por defecto
@@ -39,7 +39,7 @@
Esto eliminará todos los códigos de acceso guardados de la billetera. Cualquier operación posterior con la billetera requerirá introducir el código de acceso.Eliminar la tarjeta guardada borra todos las billeteras guardadas y sus códigos de acceso de la app.Guardar código de acceso
- Se solicitará la autenticación biométrica en lugar del código de acceso para interactuar con su tarjeta.
+ Se solicitará la autenticación biométrica en lugar del código de acceso para las interacciones con su tarjeta o anillo.Mantener la billetera en la appHabilite para vincular todos las billeteras a la app Tangem. Se requerirá autenticación biométrica para desbloquear la app. La firma de transacciones requiere tocar su tarjeta Tangem.Oscuro
@@ -51,6 +51,8 @@
No mostrar de nuevoEntendidoLos saldos están ocultos
+ Según los desarrolladores de la blockchain, los tokens de Kaspa se encuentran actualmente en fase beta. ¡Estén atentos a las actualizaciones!
+ Modo BetaPor favor, escanee la tarjeta/anilloPor favor, inténtelo de nuevo en 30 segundos o escanee la tarjeta/anilloDemasiados intentos
@@ -64,17 +66,17 @@
Desactive esta opción si no quiere que esta tarjeta se use para reiniciar códigos de acceso en otras tarjetas de esta billetera. Tenga en cuenta que esto también evitará que reinicie el código de acceso en esta tarjeta.Permite usar esta tarjeta para reiniciar el código de acceso en otras tarjetas de esta billeteraRecuperación de código de acceso
- Reiniciar
+ Resetear¿Está seguro de que quiere hacer esto?Cambiar código de accesoEl código de acceso se cambiará solo en esta tarjeta o este anillo
- Todas las tarjetas de la billetera seleccionada se han restablecido a la configuración de fábrica. Ahora puedes crear una nueva billetera.
+ Todos los dispositivos de la billetera seleccionada se han restablecido a la configuración de fábrica. Ahora puedes crear una nueva billetera.Reinicio completado¿Quiere restablecer el siguiente dispositivo en esta billetera?
- Reinicio de tarjeta
- Recomendamos completar el proceso de reinicio para todas las tarjetas en esta billetera.
+ Reseteo de billetera
+ Recomendamos completar el proceso de reinicio para todos los dispositivos en esta billetera.No ha reseteado todas sus dispositivos Tangem
- Restablecer a ajustes de fábrica
+ Resetear a configuración de fábricaModo de seguridadAjustes del dispositivoAdemás de la tarifa de red, la red Cardano cobra %1$s ADA al realizar transacciones con el %2$s token
@@ -234,7 +236,7 @@
Código de accesoDeberá ingresar la contraseña correcta antes de escanear la tarjeta.Sostenga la tarjeta firmemente
- Este mecanismo protege contra ataques sin contacto a la tarjeta. Hay un retraso entre la recepción y la ejecución del pedido. Después de la primera transacción firmada, ese teléfono se asociará con la tarjeta y las transacciones se firmarán inmediatamente.
+ Este mecanismo protege contra los ataques de proximidad a una tarjeta o anillo. Aplicará un retardo entre la recepción y la ejecución de un comando.ContraseñaAntes de ejecutar un comando que cambie el estado de la tarjeta, deberá ingresar una contraseña.Programa de referidos
@@ -251,14 +253,14 @@
DetallesCompruebe su conexión a internet o cambia a una red diferenteCondiciones de uso
- Ha usado una tarjeta de otro wallet. Toque la tarjeta asociada con esta billetera
+ Ha usado una tarjeta de otra billetera. Toque la tarjeta asociada con esta billeteraMis tokensAún no ha añadido ningún token. Agregue tokens a través de Market para hacer swapNo se puede intercambiar por %sProporcionado porEstadoTangem ofrece swaps de tokens a través de proveedores externos según los términos de cada proveedor
- Elige un proveedor
+ Elija proveedorHa ocurrido un error. Código: %sError %1$s. El proveedor seleccionado no puede procesar la transacción especificada. Por favor, redondee el valor a %2$s o cámbieloEl proveedor seleccionado no está disponible actualmente. Inténtelo de nuevo más tarde. (Código: %s)
@@ -334,7 +336,7 @@
Para continuar, de autorización a los smart contracts de %1s para usar su %2sDar autorizaciónIlimitado
- Ordenar
+ Pedir TangemEscaneeEsta información fue generada con IA.\nPulse aquí si encuentra algún error.Para cambiar el código de acceso coloque la tarjeta o el anillo como se muestra arriba y no lo retire hasta el fin de la operación
@@ -342,7 +344,7 @@
Para crear la billetera, coloque la tarjeta o el anillo como se muestra arriba y no la retire hasta el fin de la operaciónPara crear la billetera, ponga el anillo como se muestra arriba y manténgala hasta que termine la operación.Toque la tarjeta no. %s de la billetera
- Coloque para escanear
+ Acerque para escanearToque para firmarColoque la tarjeta o el anilloHa actualizado la biometría, escanee su tarjeta o anillo para entrar
@@ -357,7 +359,7 @@
Para comenzar a seguir tus activos crypto y transacciones, agregue tokensGestionar tokensPara acceder a todas las redes necesita escanear la tarjeta
- Escanee su tarjeta
+ Escanee su tarjeta o anilloBenefíciese de %1$s tarifa de servicio en intercambios a través de Changelly del %2$s al %3$s de febreroIntercambio con Changelly, %s tarifaTokens
@@ -496,7 +498,7 @@
Vuelva a introducir su código de accesoEl código de acceso debe tener al menos 4 caracteresEl código de acceso introducido no coincide con el código de acceso inicial
- Por favor repita la operación. La tarjeta se restablecerá a la configuración de fábrica.
+ Por favor repita la operación. La tarjeta/anillo se restablecerá a la configuración de fábrica.Error de activaciónAgregar tokensHa agregado una tarjeta/anillo de backup. Cuando el proceso de backup finalice, no podrá añadir más dispositivos de backup. Si tiene otra tarjeta o anillo, agréguela al backup. ¿Quiere continuar el proceso de backup?
@@ -601,7 +603,7 @@
Seleccione el país correcto para garantizar opciones de pago y servicios precisos.AjustesPuede comprobar el estado de la transacción desde la página del token.
- Puede comprobar el estado de la transacción desde la página del token
+ Puede comprobar el estado de la transacción desde la página detallada del tokenVíaAgruparPor saldo
@@ -646,14 +648,14 @@
%d billetera%d billeteras
- Restablecer la tarjeta
+ Resetear la tarjetaEntiendo que después de realizar esta acción, ya no tendré acceso a la billetera actualEntiendo que no puedo usar esta tarjeta para recuperar mi código de acceso en las otras tarjetas de la wallet actualEl restablecimiento de fábrica eliminará completamente la billetera de la tarjeta seleccionada. No podrá restaurar la billetera actual ni usar la tarjeta para recuperar el código de acceso.
- El restablecimiento de fábrica eliminará completamente la billetera de la tarjeta seleccionada y lo eliminará de la app. No podrá restaurar la billetera actual.
+ El reseteo a valores de fábrica eliminará completamente la billetera de la tarjeta/anillo seleccionado y lo eliminará de la app. No podrá restaurar la billetera actual.Si tienes un Anillo Tangem, ¡3 swaps sin comisión en Changelly hasta el 15/11!
- ¡Intercambia con 0%% de comisión!
- Inicie sesión en la app y comprueba su saldo sin escanear la tarjeta
+ ¡Intercambia con 0% de comisión!
+ Inicie sesión en la app y comprueba su saldo sin escanear la tarjeta o el anilloAcceder a la appPermitir el uso de biometríaSe solicitará la biometría en lugar del código de acceso para interactuar con su billetera
@@ -662,9 +664,9 @@
Activar la autorización biométrica¿Le gustaría usar la biometría?Tenga en cuenta que realizar una transacción con sus fondos seguirá requiriendo su tarjeta
- Escanee su tarjeta
- Escanee la tarjeta para cambiar sus ajustes. Los cambios afectarán solo a la tarjeta que has escaneado y no afectarán a otras tarjetas vinculadas a su billetera.
- ¡Prepare su tarjeta!
+ Escanear tarjeta o anillo
+ Escanee la tarjeta o el anillo para cambiar su configuración. Los cambios afectarán solo a la tarjeta o el anillo que haya escaneado y no afectarán a otros dispositivos vinculados a su billetera.
+ ¡Prepare su tarjeta/anillo!Alerta de seguridadNo tiene fondos suficientes en su saldo para vender esta criptomoneda. Deposite el activo deseado para continuar.Saldo insuficiente
@@ -772,7 +774,7 @@
Método para recibir recompensas por apuesta.\nPuede ser automático, donde la recompensa se acredita en tu dirección, o manual, donde debes retirar la recompensa creando una transacción para recibirla.Calendario de recompensasEste es un cronograma que determina cuándo los participantes reciben sus recompensas. La duración de la distribución de recompensas puede variar ligeramente según el validador y la carga de la red.
- Recompensas para reclamar: %s
+ Recompensas : %sStaking %sPeriodo de disociaciónEl período que debes esperar después de solicitar el retiro de fondos del staking antes de que los tokens estén disponibles.
@@ -857,7 +859,7 @@
Billetera de hardware revolucionariaHasta 3 tarjetas físicas o anillos por billeteraBackup ultra seguro
- Una billetera de hardware para su Bitcoin, Ethereum y muchas más monedas simultáneamente – todo en una sola tarjeta
+ Una billetera de hardware para su Bitcoin, Ethereum y muchas más monedas simultáneamente – todo en una sola tarjeta o anilloMiles de monedasÚselo en cualquier lugar, en cualquier momento. Sin cables ni baterías. Solo toque la tarjeta con su teléfono cuando necesites su cripto.La billetera para todos
@@ -871,7 +873,7 @@
El monto incluye:\n• tarifas del proveedor de servicios\n• tarifas de red por enviar %1$s desde el intercambio a la dirección del usuario. \n\nEl slippage del proveedor puede alcanzar el %2$sEl importe incluye los honorarios del proveedor de servicios.El importe incluye las tarifas del proveedor de servicios. \n\nEl slippage del proveedor puede alcanzar el %s
- Tarifa
+ InformaciónTodos los exchanges descentralizados requieren aprobaciones para evitar que los smart contracts accedan a su billetera sin su permiso. Por diseño, los smart contracts no pueden acceder a tus tokens a menos que lo apruebes. Al \"desbloquear\" sus tokens, autoriza al smart contract de 1-inch a gastarlos. Los mineros de la red reciben una tarifa de gas (pagada por voz) para registrar esta acción en la blockchain. Puede intercambiar su token después de dar la aprobación.AprobarError en la estimación de la tarifa. Envíe sus comentarios al servicio de asistencia.
@@ -910,6 +912,7 @@
Cambie este token por otro por una tarifa de servicio de %1$s del %2$s al %3$s de febrero.Intercambio con Changelly, %s tarifaIntercambie ahora
+ Crypto-monnaies populaire 🔥No disponible para compraNo disponible para venderNo disponible para cambio desde %s
@@ -953,7 +956,7 @@
Desbloquear todo con %sLa blockchain está Inaccesible. Inténtelo más tardeEscanee la tarjeta o el anillo
- Esta billetera ya ha sido activada anteriormente.\nSi no fue usted quien lo hizo, comuníquese con el servicio de asistencia.\nTangem nunca vende billeteras junto con el código de acceso generado previamente.
+ Esta billetera ya ha sido activada anteriormente.\nSi no fue usted quien lo hizo, comuníquese con el servicio de asistencia.\nTangem nunca vende billeteras junto con un código de acceso generado previamente.Solicitud para firmar un mensaje.\n\n%sDapp %1$s, solicitando\nfirmar transacción BNB.\n\n%2$sOrden de intercambio por %1$s\nPrecio: %2$s\nCantidad a recibir: %3$s\nCantidad a pagar: %4$s
@@ -991,15 +994,15 @@
%s redLa dirección se copió correctamenteSin conexión a internet
- Consíguelo ahora con un 10 %% de descuento
+ Consíguelo ahora con un 10 % de descuentoAccede a más de 13 000 criptomonedas. Compra, vende, intercambia y realiza staking con un solo toque.\nVincula hasta tres tarjetas para hacer copias de seguridad.Descubre Tangem Wallet
- Ajusta de la wallet
+ Ajustes de la walletTangemUse %s o escanee una tarjeta/anillo para desbloquear el acceso a su billeteraEl proceso de obtención de permisos está actualmente en marcha y se completará pronto.Aprobación en curso
- Parece que la activación de la tarjeta no ha ido correctamente. Esto puede deberse a un problema con el módulo NFC de su dispositivo o a una mala conexión de la tarjeta de su dispositivo. Comuníquese con nuestro equipo de soporte para obtener ayuda.
+ Parece que la activación de la tarjeta no ha funcionado correctamente. Esto puede deberse a un problema con el módulo NFC de su dispositivo o a una mala conexión de la tarjeta con su dispositivo. Comuníquese con nuestro equipo de soporte para obtener ayuda.Error de activaciónEl 3 de diciembre de 2024, la red BEP-2 fue desactivada por decisión de los desarrolladores de la red y ya no es compatibleBNB Beacon Chain se cerrará
@@ -1063,7 +1066,7 @@
¿Disfrutando de Tangem?Deba asociar su token antes de recibir tokensSe requiere tarifa de alquiler de red
- ¡Gracias! ¡Todo está listo! No se requieren más acciones.
+ ¡Gracias! ¡Todo listo! No se requieren más acciones.Ahora será redirigido al sitio web oficial de Tangem. Por favor, lea y siga las instrucciones allí indicadas.¿Alguna vez contactó al equipo de soporte de Tangem directamente desde esta aplicación?Actualización de seguridad obligatoria
@@ -1072,7 +1075,7 @@
La red Solana está congestionada. Si su transacción no se procesa dentro de 2 minutos, repita la transacción.Alerta de red SolanaLa red Solana cobra un alquiler de %1$s cada %2$s días. Las cuentas que no pueden pagar el alquiler son eliminadas de la red. Deposite en su cuenta más de 2 para usarla de forma gratuita.
- Algunas redes no están disponibles actualmente. Por favor, inténtalo de nuevo más tarde.
+ Deslice hacia abajo para refrescar o inténtelo de nuevo más tarde.Algunas redes no están disponiblesEsta es una tarjeta de Testnet. No puede procesar transacciones y solo deba usarse para pruebas y desarrollo.Solo para fines de prueba
@@ -1084,7 +1087,7 @@
Reanudar backupEsta es una acción irreversibleIniciar sesión con %s
- Escanee la tarjeta
- Use %s o escanee una tarjeta para acceder a la app
+ Escanee la tarjeta o el anillo
+ Use %s o escanee una tarjeta/anillo para acceder a la app¡Bienvenido de nuevo!
diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml
index 86ef15600b..3496503f2a 100644
--- a/core/res/src/main/res/values-fr/strings.xml
+++ b/core/res/src/main/res/values-fr/strings.xml
@@ -654,7 +654,7 @@
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 ont droit à 3 swap gratis sur Changelly jusqu\'au 15/11 !
- Échangez avec 0 %% de frais !
+ Échangez avec 0 % de frais !Connectez-vous à l\'application et vérifiez votre solde sans scanner la carteAccéder à l\'applicationAutoriser l\'utilisation de la biométrie
@@ -912,6 +912,7 @@
Échangez ce jeton contre un autre moyennant des frais de service de %1$s du %2$s au %3$s février.Échangez avec Changelly, %s fraisÉchangez maintenant
+ Crypto-monnaies populaire 🔥Non disponible à l\'achatIndisponible à la venteNon disponible pour l\'échange de %s
@@ -993,7 +994,7 @@
%s réseauL\'adresse a été copiée avec succèsPas de connexion internet
- Obtenez-le maintenant avec 10 %% de réduction
+ Obtenez-le maintenant avec 10 % de réductionAccédez à plus de 13 000 cryptomonnaies. Achetez, vendez, échangez et stakez en un seul clic.\nAssociez jusqu\'à trois cartes pour une sauvegarde.Découvrez le Portefeuille TangemParamètres du portefeuille
diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml
index a8301f66bd..d7232f22fd 100644
--- a/core/res/src/main/res/values-ja/strings.xml
+++ b/core/res/src/main/res/values-ja/strings.xml
@@ -86,6 +86,8 @@
ADAが不足しています。受け入れるアクセスが拒否されました
+ ポートフォリオに追加
+ トークンを追加すべて許可するアナリティクス
@@ -335,6 +337,8 @@
無制限Tangemを注文Tangemをスキャン
+ %sへ
+ %s内この情報はAIで生成されました。 \nエラーが見つかった場合は、ここをタップしてください。アクセスコードを変更するには、上図のようにカードまたはリングをタップし、操作が終了するまで取り外さないでください。パスコードを変更するには、上記のようにカードをタップし、操作が終了するまで取り外さないでください。
@@ -644,7 +648,7 @@
工場出荷時設定にリセットすると、選択したカードやリングからウォレットが完全に削除されます。現在のウォレットを復元したり、カードやリングを使用してアクセスコードを復元することはできません。工場出荷時の状態にリセットすると、選択したカードやリングからウォレットが完全に削除され、アプリから削除されます。現在のウォレットを復元することはできません。Tangem Ringユーザーは、11/15日までChangelly経由でスワップを3回手数料ゼロで行えます!
- 今すぐ手数料0%%でスワップしましょう!
+ 今すぐ手数料0% でスワップしましょう!アプリにログインして、カードまたはリングをスキャンせずに残高を確認できますアプリにアクセスする生体認証の使用を許可する
@@ -776,6 +780,8 @@
移行ネイティブステーキング現在、ステーキングに使用できるアクティブなバリデータは見つかりません。しばらくしてからもう一度お試しください。
+ Cardanoネットワークでステーキングする場合、残高全体が使用されます。追加の2ADAが予約され、ステーキング解除後に返却されます。ステーキング中はADAはロックされません。
+ ADAステーキングの詳細獲得した報酬はあなたのアドレスに直接送られ、すぐ使用可能です。安全にステーキングして報酬を獲得しましょう安全にステーキングして、報酬を毎日獲得しましょう
@@ -902,6 +908,7 @@
このトークンは、2月%2$s-%3$s の間、%1$s のサービス手数料で別のトークンと交換できます。Changellyでスワップ、手数料%s今すぐスワップ
+ ホットな暗号資産🔥買付できません売却できません%sからのスワップは利用できません
@@ -935,7 +942,7 @@
新しいプロモーション情報をいち早く入手しましょうプッシュ通知を使用しますか?新しいウォレットを追加
- 本当にこのウォレットを削除してもよろしいですか?
+ このウォレットを忘れてもよろしいですか?エラーが発生しました。カードまたはリングをスキャンしてログインしてください。このウォレットはすでに保存されています。別のウォレットを追加できます。%sという名前のウォレットはすでに存在します。
@@ -983,7 +990,7 @@
%sネットワークアドレスがクリップボードにコピーされましたインターネット接続がありません
- 今すぐ10 %%オフで購入
+ 今すぐ10 % オフで購入1.3万種類以上の暗号資産にアクセス。ワンタップで買付、売却、スワップ、ステーキングが可能です。\nバックアップ用に最大3枚のカードを連携できます。Tangemウォレットを見るウォレット設定
@@ -1034,6 +1041,7 @@
取引をキャンセルしてもよろしいですか? 取引を再試行することはできません%1$s %2$sの取引が完了しませんでした。もう一度試して完了してください。未完了の取引があります
+ 最終更新日は%sですこのカードには%sの署名のみが残っています。資金をすべて引き出す必要があります。署名数が少ないです異なるネットワーク上のトークンは、異なるアドレスを持つ場合があります。資金を送金する際には、アドレスがネットワークと一致していることを再確認してください。
@@ -1054,6 +1062,10 @@
Tangemを楽しんでいますか?トークンを受け取る前に、トークンを関連付ける必要があります。ネットワーク使用料が必要です
+ ありがとうございます。準備完了です。これ以上の操作は必要ありません。
+ Tangemの公式ウェブサイトに移動します。そちらの指示に従ってください。
+ このアプリ経由でTangemサポートチームに直接連絡したことがありますか?
+ 必須のセキュリティアップデート%1$s は %2$s ネットワーク内のアセットです。%3$s 取引を行うには、ネットワーク手数料のために %4$s (%5$s) を入金する必要があります。ネットワーク料金をカバーするための%1$sが足りませんSolanaネットワークが混雑しています。2分以内に取引が完了しない場合は、再度取引を繰り返してください。
@@ -1061,6 +1073,7 @@
Solana ネットワークは 2 日ごとに%1$sのレンタル料を請求します。レンタル料を支払えないアカウントはネットワークから削除されます。アカウントに%2$s以上入金すると、無料で使用できます。下にスワイプして更新するか、後でもう一度お試しください。一部のネットワークにアクセスできません
+ 一部のトークン残高を更新できませんでしたこれはテストネットカードです。取引処理はできませんので、テストおよび開発目的でのみご利用ください。テスト目的のみ破棄
diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 7872200a96..373ef88731 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -672,7 +672,7 @@
Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты или кольца. Вы не сможете восстановить текущий кошелек или использовать данную карту или кольцо для восстановления кода доступа.Сброс к заводским настройкам приведет к полному удалению кошелька с выбранной карты или кольца. Вы не сможете восстановить текущий кошелек.Владельцам колец — 3 обмена без комиссии на Changelly до 15.11!
- Обмен с 0%% комиссией!
+ Обмен с 0% комиссией!Войдите в приложение и следите за своим балансом без сканирования карты или кольцаДоступ в приложениеИспользовать биометрию
@@ -929,6 +929,7 @@
Обменивайте этот токен на другие с %1$s комиссии за обслуживание с %2$s по %3$s февраля.Обмен с Changelly, %s комиссииОбменять
+ В тренде🔥Недоступно для покупкиНедоступно для продажиНедоступно для обмена с %s
@@ -962,7 +963,7 @@
Узнавайте первым о новых акцияхХотите использовать Push-уведомления?Добавить новый кошелек
- Вы уверены, что хотите удалить этот кошелек?
+ Вы уверены, что хотите забыть этот кошелек?Произошла ошибка, пожалуйста, отсканируйте свою карту или кольцо для входаЭтот кошелек уже был сохранен, вы можете добавить другойКошелек с именем %s уже существует
@@ -1010,7 +1011,7 @@
Сеть %sАдрес скопирован в буфер обменаНет соединения с интернетом
- Получить с 10%% скидкой
+ Получить с 10% скидкойПолучите доступ к более чем 13 000 криптовалют. Покупайте, продавайте, обменивайте и стейкайте в один клик. Свяжите до трех карт для резервного копирования. Откройте Tangem WalletНастройки кошелька
diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml
index 32c50d1bcf..70bf6356ac 100644
--- a/core/res/src/main/res/values-uk-rUA/strings.xml
+++ b/core/res/src/main/res/values-uk-rUA/strings.xml
@@ -51,6 +51,8 @@
Більше не показуватиЗрозумілоБаланси приховані
+ Згідно інформації від розробників мережі, токени Kaspa знаходяться у режимі бета. Слідкуйте за оновленнями!
+ Бета режимБудь ласка, відскануйте картку або кільцеБудь ласка, спробуйте знову через 30 секунд або відскануйте картку або кільцеЗабагато спроб
@@ -672,7 +674,7 @@
Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки або кільця. Ви не зможете відновити поточний гаманець або використати цю картку або кільце для відновлення коду доступу.Скидання до заводських налаштувань призведе до повного видалення гаманця з обраної картки або кільця. Ви не зможете відновити поточний гаманець.Власникам кілець - 3 обміни без комісії на Changelly до 15.11!
- Обмін з 0%% комісією!
+ Обмін з 0% комісією!Увійдіть у додаток та слідкуйте за своїм балансом без сканування картки чи кільцяДоступ до додаткуВикористовувати біометрію
@@ -930,6 +932,7 @@
Обмінюйте цей токен на інші з %1$s комісією за обслуговування з %2$s по %3$s лютого.Обмін із Changelly, %s комісіїОбміняти
+ В тренді 🔥Недоступно для покупкиНедоступно для продажуНедоступно для обміну з %s
@@ -1011,7 +1014,7 @@
Мережа %sАдреса скопійована в буфер обмінуНемає підключення до інтернету
- Отримати з 10%% знижкою
+ Отримати з 10% знижкоюДоступ до 13,000+ криптовалют. Купуйте, продавайте, обмінюйте та стейкайте одним дотиком.\nЗ’єднайте до трьох карток для бекапу.Відкрийте Tangem WalletНалаштування гаманця
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 1255b3a06e..0fc0d39a01 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -87,6 +87,8 @@
Not enough ADAAcceptAccess denied
+ Add to portfolio
+ Add tokenAllAllowAnalytics
@@ -140,6 +142,7 @@
Synchronize addressesGo to providerGo to token
+ HidehourImportIn progress
@@ -312,6 +315,9 @@
Bought %sBuying %sBuying %s...
+ Hide this transaction
+ Once hidden, the transaction status cannot be viewed again. You can simply swipe to dismiss instead.
+ Hide Transaction Status?No tokens found. Please try another requestID: %sTransaction ID copied
@@ -338,6 +344,8 @@
UnlimitedOrder TangemScan Tangem
+ to %s
+ In %sThis information was generated with AI.\nTap here, if you find any errors.To change the access code tap the card or ring as shown above and do not remove until the end of the operationTo change the passcode tap the card as shown above and do not remove until the end of the operation
@@ -654,7 +662,7 @@
Factory Reset will completely delete the wallet from the selected card or ring. You will not be able to restore the current wallet or use the card or ring to recover the access code.Factory Reset will completely delete the wallet from the selected card or ring and remove it from the app. You will not be able to restore the current wallet.Ring owners get 3 commission-free swaps on Changelly until 15.11!
- Swap With 0%% Fees Now!
+ Swap With 0% Fees Now!Log into the app and check your balance without scanning the card or ringAccess the appAllow to use biometrics
@@ -786,6 +794,8 @@
MigrateNative stakingNo active validators available for staking at the moment. Please try again later.
+ When staking in the Cardano network, the entire balance is used. An additional 2 ADA will be reserved and returned after unstaking. Your ADA is not locked while staking.
+ ADA Staking DetailsEarned rewards will be sent to your wallet and available for use immediatelyStake securely and start earning your rewardsStake securely and start earning daily rewards
@@ -799,6 +809,8 @@
Earn staking rewardsYour remaining staked balance will be too low to unstake. You’ll need to stake more to meet the minimum unstake amount.Low staked balance
+ A minimum of %1$s %2$s is required for restaking. Please top up your balance.
+ Not enough %sStaking is currently unavailable due to network conditions. Please try again later.Staking in the %1$s network with a new validator will automatically transfer all previously staked funds to this validatorReinvests your earned rewards in your staked amount, increasing potential earnings.
@@ -912,6 +924,7 @@
Exchange this token for another at %1$s service fees from February %2$s-%3$s.Swap with Changelly, %s feesSwap now
+ Hot crypto 🔥Unavailable to purchaseUnavailable to sellUnavailable for swap from %s
@@ -945,7 +958,7 @@
Be the first to know about new promotionsWould you like to use\nPush-notifications?Add new wallet
- Are you sure you want to delete this wallet?
+ Are you sure you want to forget this wallet?An error has occurred, please scan your card or ring to log inThis wallet has already been saved, you can add another oneThe wallet with name %s already exists
@@ -955,7 +968,7 @@
Unlock all with %sBlockchain is unreachable. Try laterScan card or ring
- This wallet has already been activated earlier.\nIf it was done not by you please contact support.\nTangem never sells wallets along with the pre-generated access code.
+ This wallet has already been activated earlier.\nIf it was not done by you, please contact support.\nTangem never sells wallets along with pre-generated access codes.Requesting to sign a message.\n\n%sDapp %1$s, requesting to\nsign BNB transaction.\n\n%2$sTrade order for %1$s\nPrice: %2$s\nAmount to receive: %3$s\nAmount to pay: %4$s
@@ -993,7 +1006,7 @@
%s networkAddress was copied to clipboardNo internet connection
- Get now with 10%% off
+ Get now with 10% offAccess 13,000+ cryptocurrencies. Buy, sell, swap, and stake with a single tap.\nLink up to three cards for a backup.Discover Tangem WalletWallet settings
@@ -1044,6 +1057,7 @@
Are you sure you want to cancel the transaction? You will not be able to retry the transaction againYour transaction with an amount of %1$s %2$s was not completed. You can try again to complete it.You have unfinished transaction
+ Last update was %sOnly %s signatures are left on this card. You must withdraw all of your funds.Low signature countTokens on different networks can have different addresses. Double-check that your address matches the network when you transfer funds.
@@ -1076,6 +1090,7 @@
Solana network charges a rent of %1$s every 2 days. Accounts that can\'t afford the rent are purged from the network. Deposit your account with more than %2$s to use it for free.Swipe down to refresh or try again later.Some networks are unreachable
+ Some token balances could not be updatedThis is a Testnet card. It cannot process transactions and should only be used for testing and development purposes.For testing purposes onlyDiscard
diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt
index fb8608e78b..7b9c905f0d 100644
--- a/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt
+++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/CryptoCurrencyFactory.kt
@@ -89,7 +89,7 @@ class CryptoCurrencyFactory(
return CryptoCurrency.Coin(
id = getCoinId(network, blockchain.toCoinId()),
network = network,
- name = blockchain.fullName,
+ name = blockchain.getCoinName(),
symbol = blockchain.currency,
iconUrl = getCoinIconUrl(blockchain),
decimals = blockchain.decimals(),
diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt
index 594efd38f4..b27a7f17ef 100644
--- a/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt
+++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/NetworkOperations.kt
@@ -30,7 +30,7 @@ fun getNetwork(
return Network(
id = Network.ID(blockchain.id),
backendId = blockchain.toNetworkId(),
- name = blockchain.getNetworkName(),
+ name = blockchain.fullName,
isTestnet = blockchain.isTestnet(),
derivationPath = getNetworkDerivationPath(
blockchain = blockchain,
@@ -59,7 +59,7 @@ fun getNetwork(
return Network(
id = networkId,
backendId = blockchain.toNetworkId(),
- name = blockchain.getNetworkName(),
+ name = blockchain.fullName,
isTestnet = blockchain.isTestnet(),
derivationPath = derivationPath,
currencySymbol = blockchain.currency,
diff --git a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt
index 7cda282ecb..24e9f844e5 100644
--- a/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt
+++ b/data/common/src/main/kotlin/com/tangem/data/common/currency/ResponseCryptoCurrenciesFactory.kt
@@ -2,7 +2,6 @@ package com.tangem.data.common.currency
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.Token
-import com.tangem.blockchainsdk.compatibility.l2BlockchainsList
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.toCoinId
@@ -78,7 +77,7 @@ class ResponseCryptoCurrenciesFactory(
return CryptoCurrency.Coin(
id = getCoinId(network, blockchain.toCoinId()),
network = network,
- name = blockchain.getNameForCoin(responseToken),
+ name = blockchain.getCoinName(),
symbol = blockchain.getSymbolForCoin(responseToken),
decimals = responseToken.decimals,
iconUrl = getCoinIconUrl(blockchain),
@@ -86,21 +85,6 @@ class ResponseCryptoCurrenciesFactory(
)
}
- private fun Blockchain.getNameForCoin(responseToken: UserTokensResponse.Token): String {
- return when (this) {
- // workaround: for Blockchains full name different than backend name,
- // get name and symbol from enum Blockchain until backend renamed
- // [REDACTED_JIRA]
- Blockchain.Dischain,
- Blockchain.Telos,
- Blockchain.Cronos,
- Blockchain.TON,
- in l2BlockchainsList,
- -> this.fullName
- else -> responseToken.name
- }
- }
-
private fun Blockchain.getSymbolForCoin(responseToken: UserTokensResponse.Token): String {
return when (this) {
// workaround: Dischain was renamed but backend still returns the old name,
diff --git a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt
index 6e2f02f44c..84780326f4 100644
--- a/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt
+++ b/data/manage-tokens/src/main/kotlin/com/tangem/data/managetokens/DefaultManageTokensRepository.kt
@@ -295,7 +295,7 @@ internal class DefaultManageTokensRepository(
)
return if (!canHandleBlockchain) {
- CurrencyUnsupportedState.UnsupportedNetwork(networkName = blockchain.getNetworkName())
+ CurrencyUnsupportedState.UnsupportedNetwork(networkName = blockchain.fullName)
} else {
null
}
@@ -314,10 +314,10 @@ internal class DefaultManageTokensRepository(
return when {
// refactor this later by moving all this logic in card config
blockchain == Blockchain.Solana && !supportedTokens.contains(Blockchain.Solana) -> {
- CurrencyUnsupportedState.Token.NetworkTokensUnsupported(networkName = blockchain.getNetworkName())
+ CurrencyUnsupportedState.Token.NetworkTokensUnsupported(networkName = blockchain.fullName)
}
!userWallet.scanResponse.card.canHandleToken(supportedTokens, blockchain, cardTypesResolver) -> {
- CurrencyUnsupportedState.Token.UnsupportedCurve(networkName = blockchain.getNetworkName())
+ CurrencyUnsupportedState.Token.UnsupportedCurve(networkName = blockchain.fullName)
}
else -> null
}
diff --git a/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt b/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt
index 611ccafe2b..c2b2108053 100644
--- a/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt
+++ b/data/tokens/src/main/kotlin/com/tangem/data/tokens/paging/CoinsResponseConverter.kt
@@ -32,7 +32,7 @@ internal object CoinsResponseConverter : Converter> {
Token.Network(
networkId = network.networkId,
standardType = getNetworkStandardType(blockchain).name,
- name = blockchain.getNetworkName(),
+ name = blockchain.fullName,
address = network.contractAddress,
iconUrl = getIconUrl(network.networkId, value.imageHost),
decimalCount = network.decimalCount?.toInt(),
diff --git a/domain/card/src/main/kotlin/com/tangem/domain/card/ScanCardProcessor.kt b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanCardProcessor.kt
index 9c52d3c84a..f7a54bccda 100644
--- a/domain/card/src/main/kotlin/com/tangem/domain/card/ScanCardProcessor.kt
+++ b/domain/card/src/main/kotlin/com/tangem/domain/card/ScanCardProcessor.kt
@@ -10,6 +10,7 @@ interface ScanCardProcessor {
suspend fun scan(
cardId: String? = null,
allowsRequestAccessCodeFromRepository: Boolean = false,
+ analyticsSource: AnalyticsParam.ScreensSources,
): CompletionResult
suspend fun scan(
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt
index b24eb525ae..4363b74633 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyUseCase.kt
@@ -7,12 +7,35 @@ import arrow.core.raise.either
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.repository.CurrenciesRepository
+import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
class GetCryptoCurrencyUseCase(
private val currenciesRepository: CurrenciesRepository,
) {
+ /**
+ * Returns specific cryptocurrency for a given user wallet.
+ *
+ * !!! Important Use only [CryptoCurrency.ID.value] as cryptoCurrencyId
+ *
+ * @param userWallet The user's wallet.
+ * @param cryptoCurrencyId The ID of the cryptocurrency.
+ * @return An [Either] representing success (Right) or an error (Left) in fetching the status.
+ */
+ suspend operator fun invoke(
+ userWallet: UserWallet,
+ cryptoCurrencyId: String,
+ ): Either {
+ return either {
+ if (userWallet.isMultiCurrency) {
+ getCurrency(userWallet.walletId, cryptoCurrencyId)
+ } else {
+ getPrimaryCurrency(userWallet.walletId)
+ }
+ }
+ }
+
/**
* Returns specific cryptocurrency for a given user wallet.
*
diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt
index 41d994c8c0..33c899c9d2 100644
--- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt
+++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCurrencyCheckUseCase.kt
@@ -19,7 +19,7 @@ class GetCurrencyCheckUseCase(
currencyStatus: CryptoCurrencyStatus,
amount: BigDecimal?,
fee: BigDecimal?,
- balanceAfterTransaction: BigDecimal?,
+ feeCurrencyBalanceAfterTransaction: BigDecimal?,
recipientAddress: String? = null,
): CryptoCurrencyCheck {
return withContext(dispatchers.io) {
@@ -32,7 +32,7 @@ class GetCurrencyCheckUseCase(
val rentWarning = currencyChecksRepository.getRentExemptionError(
userWalletId = userWalletId,
currencyStatus = currencyStatus,
- balanceAfterTransaction = balanceAfterTransaction ?: BigDecimal.ZERO,
+ balanceAfterTransaction = feeCurrencyBalanceAfterTransaction ?: BigDecimal.ZERO,
)
val isAccountFunded = recipientAddress?.let {
currencyChecksRepository.checkIfAccountFunded(
diff --git a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt
index 24b85a782c..48d3ead42a 100644
--- a/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt
+++ b/features/onboarding-v2/impl/src/main/kotlin/com/tangem/features/onboarding/v2/multiwallet/impl/child/backup/model/MultiWalletBackupModel.kt
@@ -5,6 +5,7 @@ import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.core.analytics.api.AnalyticsEventHandler
+import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.event.OnboardingAnalyticsEvent
import com.tangem.core.decompose.di.ComponentScoped
import com.tangem.core.decompose.model.Model
@@ -246,7 +247,9 @@ class MultiWalletBackupModel @Inject constructor(
}
private fun showCardVerificationFailedDialog(error: TangemSdkError.CardVerificationFailed) {
- analyticsEventHandler.send(event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed)
+ analyticsEventHandler.send(
+ event = OnboardingAnalyticsEvent.Onboarding.OfflineAttestationFailed(AnalyticsParam.ScreensSources.Backup),
+ )
val resource = error.localizedDescriptionRes()
val resId = resource.resId ?: com.tangem.core.ui.R.string.common_unknown_error
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt
index 4736397eb8..5369749224 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt
@@ -95,20 +95,19 @@ internal class SendNotificationFactory(
val feeError = (feeState.feeSelectorState as? FeeSelectorState.Error)?.error
val recipientAddress = state.recipientState?.addressTextField?.value
- val statusValue = cryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded
- val feeToSubtract = if (isSubtractAvailableProvider()) {
- feeValue
- } else {
- BigDecimal.ZERO
- }
- val balanceAfterTransaction = statusValue?.let { it.amount - sendingAmount - feeToSubtract }
+ val feeCurrencyBalanceAfterTransaction = getFeeCurrencyBalanceAfterTx(
+ feeCurrencyStatus = feeCryptoCurrencyStatusProvider(),
+ sendingCurrencyStatus = cryptoCurrencyStatus,
+ sendingAmount = sendingAmount,
+ feeValue = feeValue,
+ )
val currencyCheck = getCurrencyCheckUseCase(
userWalletId = userWalletId,
currencyStatus = cryptoCurrencyStatus,
amount = sendingAmount,
fee = feeValue,
recipientAddress = recipientAddress,
- balanceAfterTransaction = balanceAfterTransaction,
+ feeCurrencyBalanceAfterTransaction = feeCurrencyBalanceAfterTransaction,
)
buildList {
addErrorNotifications(
@@ -143,6 +142,23 @@ internal class SendNotificationFactory(
)
}
+ private fun getFeeCurrencyBalanceAfterTx(
+ feeCurrencyStatus: CryptoCurrencyStatus?,
+ sendingCurrencyStatus: CryptoCurrencyStatus,
+ sendingAmount: BigDecimal,
+ feeValue: BigDecimal,
+ ): BigDecimal? {
+ val sendingCurrencyBalance = sendingCurrencyStatus.value as? CryptoCurrencyStatus.Loaded
+ val feeCurrencyBalance = feeCurrencyStatus?.value as? CryptoCurrencyStatus.Loaded
+ if (feeCurrencyStatus?.value !is CryptoCurrencyStatus.Loaded) return null
+ return when {
+ feeCurrencyStatus == sendingCurrencyStatus -> sendingCurrencyBalance?.let {
+ it.amount - sendingAmount - feeValue
+ }
+ else -> feeCurrencyBalance?.let { it.amount - feeValue }
+ }
+ }
+
private suspend fun MutableList.addErrorNotifications(
feeError: GetFeeError?,
sendingAmount: BigDecimal,
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt
index cb0b0e31e9..d890ab712a 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/amount/AmountRequirementStateTransformer.kt
@@ -16,6 +16,7 @@ import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.staking.impl.R
import com.tangem.lib.crypto.BlockchainUtils.isTron
+import com.tangem.utils.isNullOrZero
import com.tangem.utils.transformer.Transformer
import java.math.BigDecimal
import java.math.RoundingMode
@@ -41,8 +42,16 @@ internal class AmountRequirementStateTransformer(
val isIntegerOnlyError = isIntegerOnlyError(amountState, actionType)
val cryptoAmount = amountState.amountTextField.cryptoAmount
- val roundedDownCrypto = cryptoAmount.value?.setScale(0, RoundingMode.DOWN)
- val value = roundedDownCrypto?.parseBigDecimal(0).orEmpty()
+ val roundedDownCrypto = cryptoAmount.value
+ ?.setScale(0, RoundingMode.DOWN)
+ ?.parseBigDecimal(0)
+ .orEmpty()
+
+ val isAmountZeroOrNull = if (amountState.amountTextField.isFiatValue) {
+ amountState.amountTextField.fiatAmount.value.isNullOrZero()
+ } else {
+ amountState.amountTextField.cryptoAmount.value.isNullOrZero()
+ }
val errorText = when {
amountState.amountTextField.isError -> amountState.amountTextField.error
@@ -50,11 +59,11 @@ internal class AmountRequirementStateTransformer(
isIntegerOnlyError -> when (actionType) {
StakingActionCommonType.Enter -> resourceReference(
R.string.staking_amount_tron_integer_error,
- wrappedList(value),
+ wrappedList(roundedDownCrypto),
)
StakingActionCommonType.Exit -> resourceReference(
R.string.staking_amount_tron_integer_error_unstaking,
- wrappedList(value),
+ wrappedList(roundedDownCrypto),
)
else -> null
}
@@ -62,7 +71,7 @@ internal class AmountRequirementStateTransformer(
}
val isError = amountState.amountTextField.isError || requirementError != null
return amountState.copy(
- isPrimaryButtonEnabled = !isError,
+ isPrimaryButtonEnabled = !isAmountZeroOrNull && !isError,
amountTextField = amountState.amountTextField.copy(
isError = isError,
isWarning = isIntegerOnlyError,
diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
index 58f5125717..432a3256c3 100644
--- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
+++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt
@@ -647,7 +647,7 @@ internal class StakingViewModel @Inject constructor(
currencyStatus = cryptoCurrencyStatus,
amount = amount,
fee = fee,
- balanceAfterTransaction = balanceAfterTransaction,
+ feeCurrencyBalanceAfterTransaction = balanceAfterTransaction,
)
stateController.update(
AddStakingNotificationsTransformer(
@@ -850,13 +850,11 @@ internal class StakingViewModel @Inject constructor(
)
getCurrencyStatusUpdatesUseCase(userWalletId, cryptoCurrencyId, false)
.conflate()
- .distinctUntilChanged()
+ .distinctUntilChangedBy { it.getOrNull()?.value?.yieldBalance }
.filter { value.currentStep == StakingStep.InitialInfo }
.onEach { maybeStatus ->
maybeStatus.fold(
ifRight = { status ->
- if (status.value !is CryptoCurrencyStatus.Loaded) return@fold
-
if (!isInitialInfoAnalyticSent) {
isInitialInfoAnalyticSent = true
val balances = status.value.yieldBalance as? YieldBalance.Data
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 84fefe7f12..298af784a2 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
@@ -409,7 +409,7 @@ internal class SwapInteractorImpl @AssistedInject constructor(
currencyStatus = fromTokenStatus,
amount = amount.value,
fee = fee,
- balanceAfterTransaction = balanceAfterTransaction,
+ feeCurrencyBalanceAfterTransaction = balanceAfterTransaction,
)
return currencyCheck
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt
index d58c9a80ae..8f5e4a3732 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/deeplink/WalletDeepLinksHandler.kt
@@ -68,7 +68,7 @@ internal class WalletDeepLinksHandler @Inject constructor(
}
private suspend fun onSellCurrencyDeepLink(userWallet: UserWallet, data: SellCurrencyDeepLink.Data) {
- val cryptoCurrency = getCryptoCurrencyUseCase(userWallet.walletId, data.currencyId).getOrNull()
+ val cryptoCurrency = getCryptoCurrencyUseCase(userWallet, data.currencyId).getOrNull()
if (cryptoCurrency == null) {
Timber.e("onSellCurrencyDeepLink cryptoCurrency is null")
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/ScanCardToUnlockWalletClickHandler.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/ScanCardToUnlockWalletClickHandler.kt
index e528262365..9026867a47 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/ScanCardToUnlockWalletClickHandler.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/ScanCardToUnlockWalletClickHandler.kt
@@ -5,6 +5,7 @@ import arrow.core.raise.either
import arrow.core.raise.ensure
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
+import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.usecase.GenerateWalletNameUseCase
@@ -22,7 +23,7 @@ internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
suspend operator fun invoke(walletId: UserWalletId): Either {
return either {
- when (val result = scanCardProcessor.scan()) {
+ when (val result = scanCardProcessor.scan(analyticsSource = AnalyticsParam.ScreensSources.Main)) {
is CompletionResult.Failure -> {
if (result.error is TangemSdkError.UserCancelled) {
scanFailsCounter++
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletTransformer.kt
deleted file mode 100644
index f0b5cf9e20..0000000000
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletTransformer.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.tangem.feature.wallet.presentation.wallet.state.transformers
-
-import com.tangem.domain.wallets.models.UserWalletId
-import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
-import timber.log.Timber
-
-internal class RenameWalletTransformer(
- userWalletId: UserWalletId,
- private val newName: String,
-) : WalletStateTransformer(userWalletId) {
-
- override fun transform(prevState: WalletState): WalletState {
- return when (prevState) {
- is WalletState.MultiCurrency.Content -> {
- prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
- }
- is WalletState.SingleCurrency.Content -> {
- prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
- }
- is WalletState.Visa.Content -> {
- prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
- }
- is WalletState.MultiCurrency.Locked,
- is WalletState.SingleCurrency.Locked,
- is WalletState.Visa.Locked,
- -> {
- Timber.e("Impossible to rename wallet in locked state")
- prevState
- }
- }
- }
-}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt
new file mode 100644
index 0000000000..9dd8ccb8f9
--- /dev/null
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/RenameWalletsTransformer.kt
@@ -0,0 +1,53 @@
+package com.tangem.feature.wallet.presentation.wallet.state.transformers
+
+import com.tangem.domain.wallets.models.UserWallet
+import com.tangem.feature.wallet.presentation.wallet.state.model.WalletScreenState
+import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
+import kotlinx.collections.immutable.toImmutableList
+import timber.log.Timber
+
+/**
+ * Transformer that renames wallets
+ *
+ * @property renamedWallets renamed wallets
+ */
+internal class RenameWalletsTransformer(
+ private val renamedWallets: List,
+) : WalletScreenStateTransformer {
+
+ override fun transform(prevState: WalletScreenState): WalletScreenState {
+ return prevState.copy(
+ wallets = prevState.wallets.map { walletState ->
+ val renamedWallet = renamedWallets.firstOrNull { it.walletId == walletState.walletCardState.id }
+
+ if (renamedWallet != null) {
+ transform(prevState = walletState, newName = renamedWallet.name)
+ } else {
+ walletState
+ }
+ }
+ .toImmutableList(),
+ )
+ }
+
+ private fun transform(prevState: WalletState, newName: String): WalletState {
+ return when (prevState) {
+ is WalletState.MultiCurrency.Content -> {
+ prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
+ }
+ is WalletState.SingleCurrency.Content -> {
+ prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
+ }
+ is WalletState.Visa.Content -> {
+ prevState.copy(walletCardState = prevState.walletCardState.copySealed(title = newName))
+ }
+ is WalletState.MultiCurrency.Locked,
+ is WalletState.SingleCurrency.Locked,
+ is WalletState.Visa.Locked,
+ -> {
+ Timber.e("Impossible to rename wallet in locked state")
+ prevState
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
index 1d56ea3290..f06a3d46c4 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletViewModel.kt
@@ -308,8 +308,8 @@ internal class WalletViewModel @Inject constructor(
),
)
}
- is WalletsUpdateActionResolver.Action.UpdateWalletName -> {
- stateHolder.update(transformer = RenameWalletTransformer(action.selectedWalletId, action.name))
+ is WalletsUpdateActionResolver.Action.RenameWallets -> {
+ stateHolder.update(transformer = RenameWalletsTransformer(renamedWallets = action.renamedWallets))
}
is WalletsUpdateActionResolver.Action.Unknown -> {
Timber.w("Unable to perform action: $action")
diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletsUpdateActionResolver.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletsUpdateActionResolver.kt
index 324b2fc7ca..2328a63d3c 100644
--- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletsUpdateActionResolver.kt
+++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/viewmodels/WalletsUpdateActionResolver.kt
@@ -67,6 +67,9 @@ internal class WalletsUpdateActionResolver @Inject constructor(
selectedWallet = selectedWallet,
)
}
+ isAnyWalletNameChanged(state, wallets) -> {
+ getRenameWalletsAction(state, wallets)
+ }
else -> getUpdateSelectedWalletAction(state, wallets, selectedWallet)
}
}
@@ -121,15 +124,35 @@ internal class WalletsUpdateActionResolver @Inject constructor(
return state.getPrevSelectedWallet().id != selectedWallet.walletId
}
+ private fun isAnyWalletNameChanged(state: WalletScreenState, wallets: List): Boolean {
+ val prevWallets = state.wallets.map { it.walletCardState.id to it.walletCardState.title }
+ val newWallets = wallets.map { it.walletId to it.name }
+
+ val prevWalletsIds = prevWallets.map { it.first }
+ val newWalletsIds = newWallets.map { it.first }
+
+ val isAnyNameChanged = (newWallets - prevWallets.toSet()).isNotEmpty()
+
+ return prevWalletsIds != newWalletsIds && isAnyNameChanged
+ }
+
+ private fun getRenameWalletsAction(state: WalletScreenState, wallets: List): Action.RenameWallets {
+ val prevWallets = state.wallets.map { it.walletCardState.id to it.walletCardState.title }
+ val newWallets = wallets.map { it.walletId to it.name }
+
+ val renamedWallets = newWallets - prevWallets.toSet()
+
+ return Action.RenameWallets(
+ renamedWallets = wallets.filter { wallet -> renamedWallets.any { it.first == wallet.walletId } },
+ )
+ }
+
private fun getUpdateSelectedWalletAction(
state: WalletScreenState,
wallets: List,
selectedWallet: UserWallet,
): Action {
return when {
- isSelectedWalletNameChanged(state, selectedWallet) -> {
- Action.UpdateWalletName(selectedWalletId = selectedWallet.walletId, name = selectedWallet.name)
- }
isSelectedWalletUnlocked(state, selectedWallet) -> {
Action.UnlockWallet(
selectedWallet = selectedWallet,
@@ -143,10 +166,6 @@ internal class WalletsUpdateActionResolver @Inject constructor(
}
}
- private fun isSelectedWalletNameChanged(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
- return state.getPrevSelectedWallet().title != selectedWallet.name
- }
-
private fun isSelectedWalletUnlocked(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
return state.isSelectedWalletLocked() && !selectedWallet.isLocked
}
@@ -215,10 +234,19 @@ internal class WalletsUpdateActionResolver @Inject constructor(
}
}
- data class UpdateWalletName(val selectedWalletId: UserWalletId, val name: String) : Action() {
+ /**
+ * Rename wallets
+ *
+ * @property renamedWallets renamed wallets
+ */
+ data class RenameWallets(val renamedWallets: List) : Action() {
override fun toString(): String {
- return "UpdateWalletName(selectedWalletId = $selectedWalletId, name = $name)"
+ return """
+ RenameWallets(
+ renamedWallets = ${renamedWallets.joinToString { it.walletId.toString() }}
+ )
+ """.trimIndent()
}
}
diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml
index 00a9fc9386..5ca76840d2 100644
--- a/gradle/dependencies.toml
+++ b/gradle/dependencies.toml
@@ -89,11 +89,11 @@ markdownComposeView = "0.5.4"
# endregion Other libraries
# region Tangem
-tangemBlockchainSdk = "release-app_5.20-916"
+tangemBlockchainSdk = "release-app_5.20-930"
#tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds
-tangemCardSdk = "release-app_5.20-423"
+tangemCardSdk = "release-app_5.20-431"
#tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^
-tangemVico = "2.0.0-alpha.25-tangem17"
+tangemVico = "2.0.0-alpha.25-tangem-developments8"
#tangemVico = "0.0.1" # Keep it! - used for local builds ^
# endregion Tangem
diff --git a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/compatibility/L2Networks.kt b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/compatibility/L2Networks.kt
index 963d14bf12..6c395cd076 100644
--- a/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/compatibility/L2Networks.kt
+++ b/libs/blockchain-sdk/src/main/java/com/tangem/blockchainsdk/compatibility/L2Networks.kt
@@ -7,17 +7,7 @@ import com.tangem.datasource.api.markets.models.response.TokenMarketInfoResponse
import com.tangem.datasource.api.tangemTech.models.CoinsResponse
import com.tangem.datasource.api.tangemTech.models.UserTokensResponse
-val l2BlockchainsList = listOf(
- Blockchain.Optimism,
- Blockchain.Arbitrum,
- Blockchain.ZkSyncEra,
- Blockchain.Manta,
- Blockchain.PolygonZkEVM,
- Blockchain.Aurora,
- Blockchain.Base,
- Blockchain.Blast,
- Blockchain.Cyber,
-)
+val l2BlockchainsList = Blockchain.entries.filter { it.isL2EthereumNetwork() }
val l2BlockchainsCoinIds = l2BlockchainsList.map { it.toCoinId() }
diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt
index ab076272bd..85abd3906e 100644
--- a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt
+++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt
@@ -143,7 +143,7 @@ object BlockchainUtils {
}
private fun getNetworkNameWithoutTestnet(blockchain: Blockchain): String {
- return blockchain.getNetworkName().replace(oldValue = " Testnet", newValue = "")
+ return blockchain.fullName.replace(oldValue = " Testnet", newValue = "")
}
fun isTokenBetaFunctionality(blockchainId: String): Boolean {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 5e944733b8..42859fc826 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -47,7 +47,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/tangem-sdk-android")
+ url = uri("https://maven.pkg.github.com/tangem-developments/tangem-sdk-android")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
@@ -56,7 +56,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/blst-android")
+ url = uri("https://maven.pkg.github.com/tangem-developments/blst-android")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
@@ -65,7 +65,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/blockchain-sdk-kotlin")
+ url = uri("https://maven.pkg.github.com/tangem-developments/blockchain-sdk-kotlin")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
@@ -74,7 +74,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/wallet-core")
+ url = uri("https://maven.pkg.github.com/tangem-developments/wallet-core")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
@@ -86,7 +86,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/vico")
+ url = uri("https://maven.pkg.github.com/tangem-developments/vico")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
@@ -97,7 +97,7 @@ dependencyResolutionManagement {
}
maven {
// setting any repository from tangem project allows maven search all packages in the project
- url = uri("https://maven.pkg.github.com/tangem/ic4j-agent")
+ url = uri("https://maven.pkg.github.com/tangem-developments/ic4j-agent")
credentials {
username = properties.getProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = properties.getProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")