Updated on 2026-08-14

This commit is contained in:
Tangem 2023-08-08 16:10:09 +03:00
parent c266b4c8c6
commit 31e4cafad0
6 changed files with 59 additions and 6 deletions

View file

@ -34,6 +34,11 @@ class CreateSecondTwinWalletTask(
return
}
if (!TwinsHelper.isTwinsCompatible(firstCardId, card.cardId)) {
callback(CompletionResult.Failure(IncompatibleTwinCard))
return
}
session.setMessage(preparingMessage)
PurgeWalletCommand(publicKey).run(session) { response ->
when (response) {

View file

@ -0,0 +1,12 @@
package com.tangem.tap.domain.twins
import com.tangem.common.core.TangemError
import com.tangem.tap.tangemSdkManager
import com.tangem.wallet.R
object IncompatibleTwinCard : TangemError(code = 50005) {
override var customMessage: String = tangemSdkManager.getString(
R.string.twin_error_wrong_twin,
)
override val messageResId: Int? = null
}

View file

@ -428,6 +428,7 @@
<string name="transaction_history_transaction_to_address">на: %s</string>
<string name="transaction_history_tx_in_progress">В процессе…</string>
<string name="twin_error_same_card">Вы отсканировали ту же карту. Для создания twin-кошелька вам необходимо отсканировать карту с номером %d</string>
<string name="twin_error_wrong_twin">Вы отсканировали не ту twin-карту. Пожалуйста, попробуйте отсканировать другую</string>
<string name="twins_onboarding_description_format">Это карта, которую вы держите в руках. У парной карты номер %s.\n\nОбе карты можно использовать для вывода средств из этого кошелька.</string>
<string name="twins_onboarding_subtitle">Один кошелек. Две карты.</string>
<string name="twins_recreate_button_format">Сканировать карту #%s</string>

View file

@ -374,6 +374,7 @@
<string name="transaction_history_error_failed_to_load">無法加載交易</string>
<string name="transaction_history_tx_in_progress">進行中…</string>
<string name="twin_error_same_card">您掃描了同一張卡片。要創建雙錢包,您需要掃描編號為 %d 的卡</string>
<string name="twin_error_wrong_twin">你掃描錯了胞胎卡。請嘗試另一個</string>
<string name="twins_onboarding_description_format">這一個是你手裡拿著的,另一個是編號為 %s 的,這兩張卡都可以用來從這個錢包中提取資金</string>
<string name="twins_onboarding_subtitle">一個錢包,兩張卡片</string>
<string name="twins_recreate_button_format">掃描卡片 #%s</string>

View file

@ -420,6 +420,7 @@
<string name="transaction_history_transaction_to_address">to: %s</string>
<string name="transaction_history_tx_in_progress">In progress…</string>
<string name="twin_error_same_card">You\'ve scanned the same card. To create a twin wallet you need to scan the card with number %d</string>
<string name="twin_error_wrong_twin">You\'ve scanned wrong twin card. Please try another one</string>
<string name="twins_onboarding_description_format">This one that you are holding in your hands and the other one with number %s.\n\nBoth cards can be used to extract funds from this wallet.</string>
<string name="twins_onboarding_subtitle">One wallet. Two cards.</string>
<string name="twins_recreate_button_format">Scan the card #%s</string>

View file

@ -4,8 +4,17 @@ import com.tangem.crypto.CryptoUtils
import com.tangem.domain.models.scan.CardDTO
object TwinsHelper {
private val firstCardSeries = listOf("CB61", "CB64")
private val secondCardSeries = listOf("CB62", "CB65")
/**
* Card compatibility
* cb61 <-> cb62
* cb64 <-> cb65
*
*/
private const val FIRST_CARD_FIRST_SERIES = "CB61"
private const val SECOND_CARD_FIRST_SERIES = "CB62"
private const val FIRST_CARD_SECOND_SERIES = "CB64"
private const val SECOND_CARD_SECOND_SERIES = "CB65"
@Suppress("MagicNumber")
fun verifyTwinPublicKey(issuerData: ByteArray, cardWalletPublicKey: ByteArray?): Boolean {
@ -16,10 +25,15 @@ object TwinsHelper {
return CryptoUtils.verify(cardWalletPublicKey, publicKey, signedKey)
}
fun getTwinCardNumber(cardId: String): TwinCardNumber? = when {
firstCardSeries.any(cardId::startsWith) -> TwinCardNumber.First
secondCardSeries.any(cardId::startsWith) -> TwinCardNumber.Second
else -> null
fun getTwinCardNumber(cardId: String): TwinCardNumber? {
val isFirstCard = cardId.startsWith(FIRST_CARD_FIRST_SERIES) ||
cardId.startsWith(FIRST_CARD_SECOND_SERIES)
if (isFirstCard) return TwinCardNumber.First
val isSecondCard = cardId.startsWith(SECOND_CARD_FIRST_SERIES) ||
cardId.startsWith(SECOND_CARD_SECOND_SERIES)
if (isSecondCard) return TwinCardNumber.Second
return null
}
@Suppress("MagicNumber")
@ -30,6 +44,25 @@ object TwinsHelper {
val twinCardNumber = getTwinCardNumber(cardId)?.number ?: 1
return "$twinCardId #$twinCardNumber"
}
/**
* Twins compatibility
* cb61 <-> cb62
* cb64 <-> cb65
*/
fun isTwinsCompatible(firstCardId: String, secondCardId: String): Boolean {
if (firstCardId.startsWith(FIRST_CARD_FIRST_SERIES) &&
secondCardId.startsWith(SECOND_CARD_FIRST_SERIES)
) {
return true
}
if (firstCardId.startsWith(FIRST_CARD_SECOND_SERIES) &&
secondCardId.startsWith(SECOND_CARD_SECOND_SERIES)
) {
return true
}
return false
}
}
enum class TwinCardNumber(val number: Int) {