Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-08 20:29:06 +04:00
parent f4755463b0
commit 3993e1d690
14 changed files with 233 additions and 133 deletions

View file

@ -134,5 +134,9 @@ interface TangemSdkManager {
initialMessage: Message,
): CompletionResult<CreateWalletResponse>
fun changeProductType(isRing: Boolean)
fun clearProductType()
// endregion
}

View file

@ -9,7 +9,6 @@ import com.tangem.TangemSdk
import com.tangem.common.*
import com.tangem.common.authentication.AuthenticationManager
import com.tangem.common.authentication.keystore.KeystoreManager
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.core.*
import com.tangem.common.extensions.ByteArrayKey
import com.tangem.common.services.secure.SecureStorage
@ -137,6 +136,14 @@ class DefaultTangemSdkManager(
scanResponse: ScanResponse,
shouldReset: Boolean,
): CompletionResult<CreateProductWalletTaskResponse> {
tangemSdk.config.setupForProduct(
if (scanResponse.cardTypesResolver.isRing()) {
ProductType.RING
} else {
ProductType.CARD
},
)
return runTaskAsync(
runnable = CreateProductWalletTask(
cardTypesResolver = scanResponse.cardTypesResolver,
@ -144,9 +151,14 @@ class DefaultTangemSdkManager(
shouldReset = shouldReset,
),
cardId = scanResponse.card.cardId,
initialMessage = Message(resources.getString(R.string.initial_message_create_wallet_body)),
initialMessage = if (scanResponse.cardTypesResolver.isRing()) {
Message(resources.getString(R.string.initial_message_create_wallet_body_ring))
} else {
Message(resources.getString(R.string.initial_message_create_wallet_body))
},
iconScanRes = if (scanResponse.cardTypesResolver.isRing()) R.drawable.img_hand_scan_ring else null,
)
.doOnResult { tangemSdk.config.setupForProduct(ProductType.ANY) }
}
override suspend fun importWallet(
@ -160,17 +172,31 @@ class DefaultTangemSdkManager(
} catch (e: TangemSdkError.MnemonicException) {
return CompletionResult.Failure(e)
}
tangemSdk.config.setupForProduct(
if (scanResponse.cardTypesResolver.isRing()) {
ProductType.RING
} else {
ProductType.CARD
},
)
return runTaskAsync(
CreateProductWalletTask(
runnable = CreateProductWalletTask(
cardTypesResolver = scanResponse.cardTypesResolver,
derivationStyleProvider = scanResponse.derivationStyleProvider,
mnemonic = defaultMnemonic,
passphrase = passphrase,
shouldReset = shouldReset,
),
scanResponse.card.cardId,
Message(resources.getString(R.string.initial_message_create_wallet_body)),
cardId = scanResponse.card.cardId,
initialMessage = if (scanResponse.cardTypesResolver.isRing()) {
Message(resources.getString(R.string.initial_message_create_wallet_body_ring))
} else {
Message(resources.getString(R.string.initial_message_create_wallet_body))
},
)
.doOnResult { tangemSdk.config.setupForProduct(ProductType.ANY) }
}
private fun sendScanResultsToAnalytics(result: CompletionResult<ScanResponse>) {
@ -381,6 +407,16 @@ class DefaultTangemSdkManager(
return runTaskAsync(task, null, initialMessage)
}
override fun changeProductType(isRing: Boolean) {
tangemSdk.config.setupForProduct(
type = if (isRing) ProductType.RING else ProductType.CARD,
)
}
override fun clearProductType() {
tangemSdk.config.setupForProduct(type = ProductType.ANY)
}
override suspend fun finalizeTwin(
secondCardPublicKey: ByteArray,
issuerKeyPair: KeyPair,
@ -398,18 +434,5 @@ class DefaultTangemSdkManager(
companion object {
private const val MAX_INITIALIZE_ATTEMPTS = 10
@Deprecated("Use [DefaultCardSdkProvider] instead")
val config = Config(
linkedTerminal = true,
allowUntrustedCards = true,
filter = CardFilter(
allowedCardTypes = FirmwareVersion.FirmwareType.values().toList(),
maxFirmwareVersion = FirmwareVersion(major = 6, minor = 33),
batchIdFilter = CardFilter.Companion.ItemFilter.Deny(
items = setOf("0027", "0030", "0031", "0035"),
),
),
)
}
}

View file

@ -174,6 +174,10 @@ class MockTangemSdkManager(
return MockProvider.createSecondTwinWallet()
}
override fun changeProductType(isRing: Boolean) = Unit
override fun clearProductType() = Unit
override suspend fun finalizeTwin(
secondCardPublicKey: ByteArray,
issuerKeyPair: KeyPair,

View file

@ -512,6 +512,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing))
tangemSdkManager.changeProductType(isRing)
backupService.proceedBackup(iconScanRes = iconScanRes) { result ->
when (result) {
is CompletionResult.Success -> {
@ -520,6 +521,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
is CompletionResult.Failure -> Unit
}
}
tangemSdkManager.clearProductType()
}
is BackupAction.WriteBackupCard -> {
val cardIndex = if (action.cardNumber > 0) action.cardNumber - 1 else action.cardNumber
@ -529,6 +531,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
store.dispatchOnMain(BackupAction.SetHasRing(hasRing = isRing))
tangemSdkManager.changeProductType(isRing)
backupService.proceedBackup(iconScanRes = iconScanRes) { result ->
when (result) {
is CompletionResult.Success -> {
@ -555,6 +558,7 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction)
}
}
}
tangemSdkManager.clearProductType()
}
is BackupAction.DiscardBackup -> {
backupService.discardSavedBackup()

View file

@ -110,7 +110,9 @@ private object BackupReducer {
is BackupAction.PrepareToWritePrimaryCard -> if (state.primaryCardId == null) {
state.copy(
primaryCardId = backupService.primaryCardId,
primaryCardBatchId = backupService.primaryCardBatchId,
backupCardIds = backupService.backupCardIds,
backupCardBatchIds = backupService.backupCardsBatchIds,
backupCardsNumber = backupService.backupCardIds.size,
backupStep = BackupStep.WritePrimaryCard,
)
@ -120,7 +122,9 @@ private object BackupReducer {
is BackupAction.PrepareToWriteBackupCard -> if (state.primaryCardId == null) {
state.copy(
primaryCardId = backupService.primaryCardId,
primaryCardBatchId = backupService.primaryCardBatchId,
backupCardIds = backupService.backupCardIds,
backupCardBatchIds = backupService.backupCardsBatchIds,
backupCardsNumber = backupService.backupCardIds.size,
backupStep = BackupStep.WriteBackupCard(action.cardNumber),
)

View file

@ -65,9 +65,11 @@ enum class OnboardingWalletStep {
data class BackupState(
val primaryCardId: String? = null,
val primaryCardBatchId: String? = null,
val backupCardsNumber: Int = 0,
val backupCards: List<Card> = emptyList(),
val backupCardIds: List<CardId> = emptyList(),
val backupCardBatchIds: List<CardId> = emptyList(),
@Transient
val backupCardsArtworks: Map<CardId, Bitmap> = emptyMap(),
val accessCode: String = "",

View file

@ -28,6 +28,8 @@ import com.tangem.core.analytics.models.Basic
import com.tangem.core.ui.extensions.setStatusBarColor
import com.tangem.datasource.utils.isNullOrEmpty
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_IDS
import com.tangem.domain.models.scan.CardDTO.Companion.RING_BATCH_PREFIX
import com.tangem.feature.onboarding.data.model.CreateWalletResponse
import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource
import com.tangem.feature.onboarding.presentation.wallet2.viewmodel.SeedPhraseMediator
@ -398,13 +400,26 @@ class OnboardingWalletFragment :
reInitCardsWidgetIfNeeded(state.backupCardsNumber)
prepareViewForFinalizeStep()
val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4))
tvHeader.text = getText(R.string.common_origin_card)
tvBody.text = getString(
R.string.onboarding_subtitle_scan_primary_card_format,
state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) },
val isRing = state.primaryCardBatchId != null && isRing(batchId = state.primaryCardBatchId)
tvHeader.text = getText(
if (isRing) R.string.common_origin_ring else R.string.common_origin_card,
)
layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_backup_origin)
tvBody.text = if (isRing) {
getString(R.string.onboarding_subtitle_scan_ring)
} else {
val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4))
getString(
R.string.onboarding_subtitle_scan_primary_card_format,
state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) },
)
}
layoutButtonsCommon.btnWalletMainAction.text = getText(
if (isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin,
)
layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WritePrimaryCard) }
@ -428,16 +443,26 @@ class OnboardingWalletFragment :
prepareViewForFinalizeStep()
val cardNumber = (state.backupStep as? BackupStep.WriteBackupCard)?.cardNumber ?: 1
val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4))
tvHeader.text = getString(R.string.onboarding_title_backup_card_format, cardNumber)
tvBody.text = getString(
R.string.onboarding_subtitle_scan_backup_card_format,
cardIdFormatter.getFormattedCardId(state.backupCardIds[cardNumber - 1]),
val isRing = isRing(batchId = state.backupCardBatchIds[cardNumber - 1])
tvHeader.text = getString(
if (isRing) R.string.onboarding_title_backup_ring else R.string.onboarding_title_backup_card,
)
tvBody.text = if (isRing) {
getString(R.string.onboarding_subtitle_scan_ring)
} else {
val cardIdFormatter = CardIdFormatter(CardIdDisplayFormat.LastMasked(4))
getString(
R.string.onboarding_subtitle_scan_primary_card_format,
state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) },
)
}
layoutButtonsCommon.btnWalletMainAction.text = getString(
R.string.onboarding_button_backup_card_format,
cardNumber,
if (isRing) R.string.onboarding_button_backup_ring else R.string.onboarding_button_backup_origin,
)
layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
layoutButtonsCommon.btnWalletMainAction.setOnClickListener {
store.dispatch(BackupAction.WriteBackupCard(cardNumber))
@ -565,4 +590,8 @@ class OnboardingWalletFragment :
}
}
}
private fun isRing(batchId: String): Boolean {
return RING_BATCH_IDS.contains(batchId) || batchId.startsWith(RING_BATCH_PREFIX)
}
}