Updated on 2026-08-14
This commit is contained in:
commit
7e5716a13d
13 changed files with 65 additions and 38 deletions
|
|
@ -1 +1 @@
|
|||
Subproject commit 0cf3af21e6f441e6323a1ba127ee7518168797df
|
||||
Subproject commit e80938f7d9ba378a91ac544a9170597e64afa696
|
||||
|
|
@ -99,11 +99,10 @@ class TapWalletManager {
|
|||
store.dispatch(WalletAction.SetIfTestnetCard(data.card.isTestCard))
|
||||
store.dispatch(WalletAction.MultiWallet.SetIsMultiwalletAllowed(data.card.isMultiwalletAllowed))
|
||||
if (data.card.isTwinCard()) {
|
||||
val secondCardId = TwinsHelper.getTwinsCardId(data.card.cardId)
|
||||
val cardNumber = TwinsHelper.getTwinCardNumber(data.card.cardId)
|
||||
if (secondCardId != null && cardNumber != null) {
|
||||
if (cardNumber != null) {
|
||||
store.dispatch(WalletAction.TwinsAction.SetTwinCard(
|
||||
secondCardId, cardNumber, isCreatingTwinCardsAllowed = true
|
||||
cardNumber, isCreatingTwinCardsAllowed = true
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import com.tangem.tap.domain.TapSdkError
|
|||
import com.tangem.tap.domain.TapWorkarounds.isExcluded
|
||||
import com.tangem.tap.domain.TapWorkarounds.isMultiCurrencyWallet
|
||||
import com.tangem.tap.domain.TapWorkarounds.noteCurrency
|
||||
import com.tangem.tap.domain.TapWorkarounds.isNote
|
||||
import com.tangem.tap.domain.extensions.getSingleWallet
|
||||
import com.tangem.tap.domain.twins.TwinCardsManager
|
||||
import com.tangem.tap.domain.twins.isTwinCard
|
||||
|
|
@ -31,7 +32,6 @@ data class ScanNoteResponse(
|
|||
val walletData: WalletData?,
|
||||
val secondTwinPublicKey: String? = null,
|
||||
) : CommandResponse {
|
||||
|
||||
fun getBlockchain(): Blockchain? {
|
||||
if (card.noteCurrency != null) return card.noteCurrency
|
||||
val blockchainName: String = walletData?.blockchain ?: return null
|
||||
|
|
@ -148,14 +148,14 @@ class ScanNoteTask(val card: Card? = null) : CardSessionRunnable<ScanNoteRespons
|
|||
|
||||
private fun getErrorIfExcludedCard(card: Card): TangemError? {
|
||||
if (card.isExcluded()) return TapSdkError.CardForDifferentApp
|
||||
// Disable new multi-currency HD wallet cards on the old version of the app
|
||||
if (card.isMultiCurrencyWallet()) return UpdateAppToUseThisCard()
|
||||
// Disable new cards on the old version of the app // TODO: remove when cards are supported
|
||||
if (card.isMultiCurrencyWallet() || card.isNote()) return UpdateAppToUseThisCard()
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getWalletManagerFactory(): WalletManagerFactory {
|
||||
val blockchainSdkConfig = store.state.globalState.configManager?.config
|
||||
?.blockchainSdkConfig ?: BlockchainSdkConfig()
|
||||
?.blockchainSdkConfig ?: BlockchainSdkConfig()
|
||||
return WalletManagerFactory(blockchainSdkConfig)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.tangem.common.KeyPair
|
|||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.common.core.CardSession
|
||||
import com.tangem.common.core.CardSessionRunnable
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.hexToBytes
|
||||
import com.tangem.operations.wallet.CreateWalletCommand
|
||||
import com.tangem.operations.wallet.CreateWalletResponse
|
||||
|
|
@ -13,14 +14,21 @@ import com.tangem.operations.wallet.PurgeWalletCommand
|
|||
import com.tangem.tap.domain.extensions.getSingleWallet
|
||||
|
||||
class CreateSecondTwinWalletTask(
|
||||
private val firstPublicKey: String,
|
||||
private val issuerKeys: KeyPair,
|
||||
private val preparingMessage: Message,
|
||||
private val creatingWalletMessage: Message
|
||||
private val firstPublicKey: String,
|
||||
private val firstCardId: String,
|
||||
private val issuerKeys: KeyPair,
|
||||
private val preparingMessage: Message,
|
||||
private val creatingWalletMessage: Message
|
||||
) : CardSessionRunnable<CreateWalletResponse> {
|
||||
override fun run(session: CardSession, callback: (result: CompletionResult<CreateWalletResponse>) -> Unit) {
|
||||
val publicKey = session.environment.card?.getSingleWallet()?.publicKey
|
||||
val card = session.environment.card
|
||||
val publicKey = card?.getSingleWallet()?.publicKey
|
||||
if (publicKey != null) {
|
||||
if (!card.cardId.startsWith(TwinsHelper.getPairCardSeries(firstCardId) ?: "")) {
|
||||
callback(CompletionResult.Failure(TangemSdkError.WrongCardType()))
|
||||
return
|
||||
}
|
||||
|
||||
session.setInitialMessage(preparingMessage)
|
||||
PurgeWalletCommand(publicKey).run(session) { response ->
|
||||
when (response) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import com.tangem.tap.tangemSdkManager
|
|||
class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse, context: Context) {
|
||||
|
||||
private val currentCardId: String = scanNoteResponse.card.cardId
|
||||
private val secondCardId: String? = TwinsHelper.getTwinsCardId(currentCardId)
|
||||
|
||||
private var currentCardPublicKey: String? = null
|
||||
private var secondCardPublicKey: String? = null
|
||||
|
|
@ -59,13 +58,15 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse, context:
|
|||
preparingMessage: Message,
|
||||
creatingWalletMessage: Message,
|
||||
): SimpleResult {
|
||||
val task = CreateSecondTwinWalletTask(
|
||||
firstPublicKey = currentCardPublicKey!!,
|
||||
firstCardId = currentCardId,
|
||||
issuerKeys = issuerKeyPair,
|
||||
preparingMessage = preparingMessage,
|
||||
creatingWalletMessage = creatingWalletMessage
|
||||
)
|
||||
val response = tangemSdkManager.runTaskAsync(
|
||||
CreateSecondTwinWalletTask(
|
||||
firstPublicKey = currentCardPublicKey!!,
|
||||
issuerKeys = issuerKeyPair,
|
||||
preparingMessage = preparingMessage,
|
||||
creatingWalletMessage = creatingWalletMessage),
|
||||
secondCardId, initialMessage
|
||||
task, null, initialMessage
|
||||
)
|
||||
when (response) {
|
||||
is CompletionResult.Success -> {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,19 @@ class TwinsHelper {
|
|||
}
|
||||
}
|
||||
|
||||
fun getPairCardSeries(cardId: String): String? {
|
||||
return when (getTwinCardNumber(cardId) ?: return null) {
|
||||
TwinCardNumber.First -> {
|
||||
val index = firstCardSeries.indexOf(cardId.take(4))
|
||||
secondCardSeries[index]
|
||||
}
|
||||
TwinCardNumber.Second -> {
|
||||
val index = secondCardSeries.indexOf(cardId.take(4))
|
||||
firstCardSeries[index]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getTwinsCardId(cardId: String): String? {
|
||||
val cardIdWithNewSeries = when (getTwinCardNumber(cardId) ?: return null) {
|
||||
TwinCardNumber.First -> {
|
||||
|
|
|
|||
|
|
@ -172,12 +172,16 @@ private fun handleSecurityAction(
|
|||
state.copy(confirmScreenState = confirmScreenState)
|
||||
}
|
||||
is DetailsAction.ManageSecurity.SaveChanges.Success -> {
|
||||
// Setting options to show only LongTap from now on
|
||||
// Setting options to show only LongTap from now on for non-twins
|
||||
state.copy(
|
||||
securityScreenState = state.securityScreenState?.copy(
|
||||
currentOption = state.securityScreenState.selectedOption,
|
||||
allowedOptions = EnumSet.of(SecurityOption.LongTap)
|
||||
))
|
||||
securityScreenState = state.securityScreenState?.copy(
|
||||
currentOption = state.securityScreenState.selectedOption,
|
||||
allowedOptions = state.card?.let {
|
||||
prepareAllowedSecurityOptions(
|
||||
it, state.securityScreenState.selectedOption
|
||||
)
|
||||
} ?: EnumSet.of(SecurityOption.LongTap)
|
||||
))
|
||||
}
|
||||
|
||||
else -> state
|
||||
|
|
@ -188,8 +192,11 @@ private fun prepareAllowedSecurityOptions(
|
|||
card: Card?, currentSecurityOption: SecurityOption?
|
||||
): EnumSet<SecurityOption> {
|
||||
val prohibitDefaultPin = card?.settings?.isRemovingAccessCodeAllowed != true
|
||||
|
||||
val allowedSecurityOptions = EnumSet.noneOf(SecurityOption::class.java)
|
||||
|
||||
if (card?.isTwinCard() == true) {
|
||||
allowedSecurityOptions.add(SecurityOption.PassCode)
|
||||
}
|
||||
if ((currentSecurityOption == SecurityOption.LongTap) || !prohibitDefaultPin) {
|
||||
allowedSecurityOptions.add(SecurityOption.LongTap)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,8 +152,8 @@ sealed class WalletAction : Action {
|
|||
object ShowOnboarding : TwinsAction()
|
||||
object SetOnboardingShown : TwinsAction()
|
||||
data class SetTwinCard(
|
||||
val secondCardId: String, val number: TwinCardNumber,
|
||||
val isCreatingTwinCardsAllowed: Boolean,
|
||||
val number: TwinCardNumber,
|
||||
val isCreatingTwinCardsAllowed: Boolean,
|
||||
) : TwinsAction()
|
||||
}
|
||||
}
|
||||
|
|
@ -195,7 +195,6 @@ data class TradeCryptoAvailability(
|
|||
)
|
||||
|
||||
data class TwinCardsState(
|
||||
val secondCardId: String?,
|
||||
val cardNumber: TwinCardNumber?,
|
||||
val showTwinOnboarding: Boolean,
|
||||
val isCreatingTwinCardsAllowed: Boolean
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class WalletMiddleware {
|
|||
when (result) {
|
||||
is CompletionResult.Success -> {
|
||||
val scanNoteResponse =
|
||||
globalState?.scanNoteResponse?.copy(card = result.data)
|
||||
globalState?.scanNoteResponse?.copy(card = result.data)
|
||||
scanNoteResponse?.let {
|
||||
globalState.tapWalletManager.onCardScanned(scanNoteResponse)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ class TwinsReducer {
|
|||
is WalletAction.TwinsAction.SetTwinCard -> {
|
||||
state.copy(
|
||||
twinCardsState = TwinCardsState(
|
||||
secondCardId = action.secondCardId,
|
||||
cardNumber = action.number,
|
||||
showTwinOnboarding = state.twinCardsState?.showTwinOnboarding
|
||||
?: false,
|
||||
|
|
@ -21,7 +20,7 @@ class TwinsReducer {
|
|||
is WalletAction.TwinsAction.ShowOnboarding -> {
|
||||
state.copy(
|
||||
twinCardsState = state.twinCardsState?.copy(showTwinOnboarding = true)
|
||||
?: TwinCardsState(null, null,
|
||||
?: TwinCardsState(cardNumber = null,
|
||||
showTwinOnboarding = true,
|
||||
isCreatingTwinCardsAllowed = false)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
override fun newState(state: WalletState) {
|
||||
if (activity == null) return
|
||||
|
||||
if (state.isMultiwalletAllowed && walletView is SingleWalletView) {
|
||||
if (state.isMultiwalletAllowed &&
|
||||
state.primaryWallet?.currencyData?.status != BalanceStatus.EmptyCard &&
|
||||
walletView is SingleWalletView
|
||||
) {
|
||||
walletView = MultiWalletView()
|
||||
walletView.changeWalletView(this)
|
||||
} else if (!state.isMultiwalletAllowed && walletView is MultiWalletView) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import androidx.transition.TransitionInflater
|
|||
import com.squareup.picasso.Picasso
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.domain.twins.TwinsHelper
|
||||
import com.tangem.tap.features.wallet.redux.Artwork
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -34,10 +33,9 @@ class TwinsOnboardingFragment : Fragment(R.layout.fragment_twin_cards) {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
store.dispatch(WalletAction.TwinsAction.SetOnboardingShown)
|
||||
|
||||
val secondCardId = store.state.walletState.twinCardsState?.secondCardId ?: ""
|
||||
val secondTwinCardId = TwinsHelper.getTwinCardIdForUser(secondCardId)
|
||||
val text = getString(R.string.twins_onboarding_description_format, secondTwinCardId)
|
||||
val secondTwinNumber =
|
||||
store.state.walletState.twinCardsState?.cardNumber?.pairNumber()?.number ?: ""
|
||||
val text = getString(R.string.twins_onboarding_description_format, secondTwinNumber)
|
||||
tv_twin_cards_description_1.text = text
|
||||
|
||||
setOnClickListeners()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue