Updated on 2026-08-14

This commit is contained in:
Tangem 2022-09-15 22:26:38 +04:00
parent e074377533
commit 21997b5e9b
29 changed files with 262 additions and 119 deletions

View file

@ -64,6 +64,7 @@ sealed class TapSdkError(override val messageResId: Int?) : Throwable(), TangemE
object CardForDifferentApp : TapSdkError(R.string.alert_unsupported_card)
object CardNotSupportedByRelease : TapSdkError(R.string.error_update_app)
object ScanPrimaryCard : TapSdkError(R.string.saltpay_backup_warning)
}

View file

@ -160,6 +160,7 @@ class TapWalletManager {
val primaryWalletManager = walletManagerFactory.makePrimaryWalletManager(data)
if (blockchain != Blockchain.Unknown && primaryWalletManager != null) {
val blockchainNetwork = BlockchainNetwork.fromWalletManager(primaryWalletManager)
val primaryToken = data.getPrimaryToken()
dispatchOnMain(WalletAction.MultiWallet.SetPrimaryBlockchain(blockchain))
@ -169,9 +170,9 @@ class TapWalletManager {
}
dispatchOnMain(
WalletAction.MultiWallet.AddBlockchains(
listOf(BlockchainNetwork.fromWalletManager(primaryWalletManager)),
listOf(primaryWalletManager)
)
listOf(blockchainNetwork),
listOf(primaryWalletManager),
),
)
}
}

View file

@ -6,6 +6,7 @@ import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.extensions.toHexString
import com.tangem.common.services.Result
import com.tangem.domain.common.TapWorkarounds.isSaltPay
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
import com.tangem.domain.common.TapWorkarounds.isTangemNote
import com.tangem.domain.common.TwinCardNumber
@ -23,11 +24,14 @@ val Card.isWalletDataSupported: Boolean
val Card.isMultiwalletAllowed: Boolean
get() {
return !isTangemTwin() && !isStart2Coin && !isTangemNote()
return !isTangemTwin() && !isStart2Coin && !isTangemNote() && !isSaltPay
&& (firmwareVersion >= FirmwareVersion.MultiWalletAvailable ||
getSingleWallet()?.curve == EllipticCurve.Secp256k1)
}
val Card.isHdWalletAllowedByApp: Boolean
get() = settings.isHDWalletAllowed && !isSaltPay
fun Card.getSingleWallet(): CardWallet? {
return wallets.firstOrNull()
}

View file

@ -1,6 +1,10 @@
package com.tangem.tap.domain.extensions
import com.tangem.blockchain.common.*
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.DerivationParams
import com.tangem.blockchain.common.DerivationStyle
import com.tangem.blockchain.common.WalletManager
import com.tangem.blockchain.common.WalletManagerFactory
import com.tangem.common.card.Card
import com.tangem.common.card.CardWallet
import com.tangem.common.card.EllipticCurve
@ -35,10 +39,10 @@ fun WalletManagerFactory.makeWalletManagerForApp(
walletPublicKey = wallet.publicKey,
pairPublicKey = scanResponse.secondTwinPublicKey!!.hexToBytes(),
blockchain = environmentBlockchain,
curve = wallet.curve
curve = wallet.curve,
)
}
seedKey != null && derivationParams != null -> {
scanResponse.card.isHdWalletAllowedByApp && (seedKey != null && derivationParams != null) -> {
val derivedKeys = scanResponse.derivedKeys[wallet.publicKey.toMapKey()]
val derivationPath = when (derivationParams) {
is DerivationParams.Default -> blockchain.derivationPath(derivationParams.style)
@ -51,7 +55,7 @@ fun WalletManagerFactory.makeWalletManagerForApp(
blockchain = environmentBlockchain,
seedKey = wallet.publicKey,
derivedKey = derivedKey,
derivation = derivationParams
derivation = derivationParams,
)
}
else -> {

View file

@ -4,7 +4,6 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.common.CompletionResult
import com.tangem.common.card.Card
import com.tangem.common.card.EllipticCurve
import com.tangem.common.card.FirmwareVersion
import com.tangem.common.core.CardSession
import com.tangem.common.core.CardSessionRunnable
import com.tangem.common.core.TangemError
@ -18,10 +17,11 @@ import com.tangem.domain.common.ProductType
import com.tangem.domain.common.ScanResponse
import com.tangem.domain.common.TapWorkarounds.isExcluded
import com.tangem.domain.common.TapWorkarounds.isNotSupportedInThatRelease
import com.tangem.domain.common.TapWorkarounds.isTangemNote
import com.tangem.domain.common.TapWorkarounds.isSaltPay
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
import com.tangem.domain.common.TwinsHelper
import com.tangem.domain.common.isTangemTwins
import com.tangem.domain.common.productType
import com.tangem.operations.PreflightReadMode
import com.tangem.operations.PreflightReadTask
import com.tangem.operations.ScanTask
@ -32,6 +32,9 @@ import com.tangem.operations.issuerAndUserData.ReadIssuerDataCommand
import com.tangem.tap.domain.TapSdkError
import com.tangem.tap.domain.extensions.getPrimaryCurve
import com.tangem.tap.domain.extensions.getSingleWallet
import com.tangem.tap.domain.extensions.hasNoWallets
import com.tangem.tap.domain.extensions.isHdWalletAllowedByApp
import com.tangem.tap.domain.extensions.isMultiwalletAllowed
import com.tangem.tap.domain.tokens.CurrenciesRepository
import com.tangem.tap.domain.tokens.models.BlockchainNetwork
import com.tangem.tap.preferencesStorage
@ -60,7 +63,6 @@ class ScanProductTask(
}
val commandProcessor = when {
card.isTangemNote() -> ScanNoteProcessor()
card.isTangemTwins() -> ScanTwinProcessor()
else -> ScanWalletProcessor(currenciesRepository, additionalBlockchainsToDerive)
}
@ -87,29 +89,11 @@ class ScanProductTask(
private fun getErrorIfExcludedCard(card: Card): TangemError? {
if (card.isExcluded()) return TapSdkError.CardForDifferentApp
if (card.isNotSupportedInThatRelease()) return TapSdkError.CardNotSupportedByRelease
if (card.isSaltPay && card.hasNoWallets()) return TapSdkError.ScanPrimaryCard
return null
}
}
private class ScanNoteProcessor : ProductCommandProcessor<ScanResponse> {
override fun proceed(
card: Card,
session: CardSession,
callback: (result: CompletionResult<ScanResponse>) -> Unit
) {
callback(
CompletionResult.Success(
ScanResponse(
card = card,
productType = ProductType.Note,
walletData = session.environment.walletData,
),
),
)
}
}
private class ScanWalletProcessor(
private val currenciesRepository: CurrenciesRepository?,
private val additionalBlockchainsToDerive: Collection<Blockchain>? = null
@ -123,12 +107,13 @@ private class ScanWalletProcessor(
) {
createMissingWalletsIfNeeded(card, session, callback)
}
private fun createMissingWalletsIfNeeded(
card: Card,
session: CardSession,
callback: (result: CompletionResult<ScanResponse>) -> Unit,
) {
if (card.wallets.isEmpty() || card.firmwareVersion < FirmwareVersion.MultiWalletAvailable) {
if (card.wallets.isEmpty() || !card.isMultiwalletAllowed) {
startLinkingForBackupIfNeeded(card, session, callback)
return
}
@ -186,16 +171,16 @@ private class ScanWalletProcessor(
) {
scope.launch {
val derivations = collectDerivations(card)
if (derivations.isEmpty() || !card.settings.isHDWalletAllowed) {
if (derivations.isEmpty() || !card.isHdWalletAllowedByApp) {
callback(
CompletionResult.Success(
ScanResponse(
card = card,
productType = ProductType.Wallet,
productType = card.productType,
walletData = session.environment.walletData,
primaryCard = primaryCard
)
)
primaryCard = primaryCard,
),
),
)
return@launch
}
@ -205,10 +190,10 @@ private class ScanWalletProcessor(
is CompletionResult.Success -> {
val response = ScanResponse(
card = card,
productType = ProductType.Wallet,
productType = card.productType,
walletData = session.environment.walletData,
derivedKeys = result.data.entries,
primaryCard = primaryCard
primaryCard = primaryCard,
)
callback(CompletionResult.Success(response))
}
@ -222,7 +207,7 @@ private class ScanWalletProcessor(
val currenciesRepository = currenciesRepository ?: return emptyList()
val cardCurrencies = currenciesRepository
.loadSavedCurrencies(card.cardId, card.settings.isHDWalletAllowed).toMutableList()
.loadSavedCurrencies(card.cardId, card.isHdWalletAllowedByApp).toMutableList()
val blockchainsToDerive = cardCurrencies.ifEmpty {
mutableListOf(