Updated on 2026-08-14

This commit is contained in:
Tangem 2021-05-25 20:47:59 +03:00
parent d6bee4ab41
commit 63a34103c0
8 changed files with 72 additions and 36 deletions

View file

@ -6,7 +6,6 @@ import com.tangem.commands.common.card.CardStatus
import com.tangem.commands.common.network.Result
import com.tangem.tap.common.analytics.AnalyticsEvent
import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler
import com.tangem.tap.common.redux.global.CryptoCurrencyName
import com.tangem.tap.common.redux.global.FiatCurrencyName
import com.tangem.tap.common.redux.global.GlobalAction
import com.tangem.tap.currenciesRepository
@ -150,11 +149,7 @@ class TapWalletManager {
val config = store.state.globalState.configManager?.config ?: return@withContext
val blockchain = data.card.getBlockchain()
val primaryWalletManager = if (blockchain != null) {
walletManagerFactory.makeWalletManagerForApp(data.card, blockchain)
} else {
null
}
val primaryWalletManager = walletManagerFactory.makePrimaryWalletManager(data)
if (blockchain != null && primaryWalletManager != null) {
val primaryToken = data.card.getToken()

View file

@ -6,6 +6,9 @@ import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.commands.common.card.Card
import com.tangem.commands.common.card.EllipticCurve
import com.tangem.commands.wallet.CardWallet
import com.tangem.common.extensions.hexToBytes
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.domain.twins.isTwinCard
fun WalletManagerFactory.makeWalletManagerForApp(
card: Card,
@ -32,3 +35,24 @@ fun WalletManagerFactory.makeWalletManagersForApp(
): List<WalletManager> {
return blockchains.mapNotNull { blockchain -> makeWalletManagerForApp(card, blockchain) }
}
fun WalletManagerFactory.makePrimaryWalletManager(
data: ScanNoteResponse,
): WalletManager? {
val card = data.card
val blockchain = card.getBlockchain()
val supportedCurves = blockchain?.getSupportedCurves() ?: return null
val wallets = card.getWallets().filter { wallet -> supportedCurves.contains(wallet.curve) }
val wallet = selectWallet(wallets)
val publicKey = wallet?.publicKey ?: return null
val curveToUse = wallet.curve ?: return null
return if (card.isTwinCard() && data.secondTwinPublicKey != null) {
makeMultisigWalletManager(
cardId = card.cardId,
walletPublicKey = publicKey, pairPublicKey = data.secondTwinPublicKey.hexToBytes(),
blockchain = blockchain, curve = curveToUse
)
} else {
makeWalletManager(card.cardId, publicKey, blockchain, curveToUse)
}
}

View file

@ -35,6 +35,4 @@ class CreateWalletAndRescanTask : CardSessionRunnable<Card>, PreflightReadCapabl
}
}
}
}

View file

@ -44,7 +44,7 @@ class ScanNoteTask(val card: Card? = null) : CardSessionRunnable<ScanNoteRespons
val card = this.card?.copy(
isPin1Default = result.data.isPin1Default,
isPin2Default = result.data.isPin2Default
) ?: result.data
)?.also { it.setWallets(card.getWallets()) } ?: result.data
val error = getErrorIfExcludedCard(card)
if (error != null) {

View file

@ -2,7 +2,6 @@ package com.tangem.tap.domain.twins
import com.tangem.CardSession
import com.tangem.CardSessionRunnable
import com.tangem.commands.common.card.CardStatus
import com.tangem.commands.wallet.CreateWalletResponse
import com.tangem.commands.wallet.PurgeWalletCommand
import com.tangem.common.CompletionResult
@ -14,12 +13,15 @@ import com.tangem.tasks.CreateWalletTask
class CreateFirstTwinWalletTask : CardSessionRunnable<CreateWalletResponse> {
override val requiresPin2 = false
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletResponse>) -> Unit) {
override fun run(
session: CardSession,
callback: (result: CompletionResult<CreateWalletResponse>) -> Unit,
) {
if (session.environment.card?.getSingleWallet()?.publicKey != null) {
PurgeWalletCommand(TangemSdkConstants.getDefaultWalletIndex()).run(session) { response ->
when (response) {
is CompletionResult.Success -> {
session.environment.card = session.environment.card?.copy(status = CardStatus.Empty)
session.environment.card = session.environment.card?.changeStatusToEmpty()
CreateWalletTask().run(session) { callback(it) }
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(response.error))

View file

@ -3,7 +3,6 @@ package com.tangem.tap.domain.twins
import com.tangem.CardSession
import com.tangem.CardSessionRunnable
import com.tangem.Message
import com.tangem.commands.common.card.CardStatus
import com.tangem.commands.wallet.CreateWalletResponse
import com.tangem.commands.wallet.PurgeWalletCommand
import com.tangem.common.CompletionResult
@ -26,8 +25,7 @@ class CreateSecondTwinWalletTask(
PurgeWalletCommand(TangemSdkConstants.getDefaultWalletIndex()).run(session) { response ->
when (response) {
is CompletionResult.Success -> {
session.environment.card =
session.environment.card?.copy(status = CardStatus.Empty)
session.environment.card = session.environment.card?.changeStatusToEmpty()
finishTask(session, callback)
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(response.error))
@ -43,8 +41,8 @@ class CreateSecondTwinWalletTask(
CreateWalletTask().run(session) { result ->
when (result) {
is CompletionResult.Success -> {
session.environment.card =
session.environment.card?.copy(status = CardStatus.Loaded)
session.environment.card = session.environment.card?.changeStatusToLoaded()
WriteProtectedIssuerDataTask(
firstPublicKey.hexToBytes(), TwinCardsManager.issuerKeys
).run(session) { writeResult ->

View file

@ -3,27 +3,32 @@ package com.tangem.tap.domain.twins
import com.tangem.CardSession
import com.tangem.CardSessionRunnable
import com.tangem.KeyPair
import com.tangem.commands.read.ReadCommand
import com.tangem.common.CompletionResult
import com.tangem.tap.domain.tasks.ScanNoteResponse
import com.tangem.tap.domain.tasks.ScanNoteTask
import com.tangem.tasks.PreflightReadSettings
import com.tangem.tasks.PreflightReadTask
class FinalizeTwinTask(
private val twinPublicKey: ByteArray, private val issuerKeys: KeyPair
) : CardSessionRunnable<ScanNoteResponse> {
private val twinPublicKey: ByteArray, private val issuerKeys: KeyPair,
) : CardSessionRunnable<ScanNoteResponse> {
override val requiresPin2 = true
override fun run(session: CardSession, callback: (result: CompletionResult<ScanNoteResponse>) -> Unit) {
override fun run(
session: CardSession,
callback: (result: CompletionResult<ScanNoteResponse>) -> Unit,
) {
WriteProtectedIssuerDataTask(twinPublicKey, issuerKeys).run(session) { result ->
when (result) {
is CompletionResult.Success -> {
ReadCommand().run(session) { readResult ->
is CompletionResult.Success ->
PreflightReadTask(PreflightReadSettings.FullCardRead).run(session) { readResult ->
when (readResult) {
is CompletionResult.Success -> ScanNoteTask(readResult.data).run(session, callback)
is CompletionResult.Failure -> callback(CompletionResult.Failure(readResult.error))
is CompletionResult.Success ->
ScanNoteTask(readResult.data).run(session, callback)
is CompletionResult.Failure ->
callback(CompletionResult.Failure(readResult.error))
}
}
}
is CompletionResult.Failure -> callback(CompletionResult.Failure(result.error))
}
}

View file

@ -1,7 +1,9 @@
package com.tangem.tap.domain.twins
import com.tangem.commands.common.card.Card
import com.tangem.commands.common.card.CardStatus
import com.tangem.commands.common.card.masks.Product
import com.tangem.commands.wallet.WalletStatus
import com.tangem.tap.common.extensions.isEven
class TwinsHelper {
@ -53,16 +55,16 @@ class TwinsHelper {
private fun String.calculateLuhn(): Int {
val checksum = this.reversed()
.mapIndexed { index, c ->
val digit = if (c in '0'..'9') c - '0' else c - 'A'
if (!index.isEven()) {
digit
} else {
val newDigit = digit * 2
if (newDigit >= 10) newDigit - 9 else newDigit
}
}.sum()
.rem(10)
.mapIndexed { index, c ->
val digit = if (c in '0'..'9') c - '0' else c - 'A'
if (!index.isEven()) {
digit
} else {
val newDigit = digit * 2
if (newDigit >= 10) newDigit - 9 else newDigit
}
}.sum()
.rem(10)
return (10 - checksum) % 10
}
@ -81,4 +83,16 @@ fun Card.isTwinCard(): Boolean {
fun Card.getTwinCardIdForUser(): String {
return TwinsHelper.getTwinCardIdForUser(this.cardId)
}
fun Card.changeStatusToLoaded(): Card {
val wallets = getWallets().map { it.copy(status = WalletStatus.Loaded) }
return copy(status = CardStatus.Loaded)
.also { it.setWallets(wallets) }
}
fun Card.changeStatusToEmpty(): Card {
val wallets = getWallets().map { it.copy(status = WalletStatus.Empty) }
return copy(status = CardStatus.Empty)
.also { it.setWallets(wallets) }
}