diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 0cf3af21e6..e80938f7d9 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 0cf3af21e6f441e6323a1ba127ee7518168797df +Subproject commit e80938f7d9ba378a91ac544a9170597e64afa696 diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index 32403ae363..9133792893 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -91,7 +91,7 @@ class TapWalletManager { store.dispatch(WalletAction.MultiWallet.SetIsMultiwalletAllowed(data.card.isMultiwalletAllowed)) if (data.card.isTangemTwin()) { data.card.getTwinCardNumber()?.let { - store.dispatch(WalletAction.TwinsAction.SetTwinCard(null, it, true)) + store.dispatch(WalletAction.TwinsAction.SetTwinCard(it, true)) } } diff --git a/app/src/main/java/com/tangem/tap/domain/tasks/ScanNoteTask.kt b/app/src/main/java/com/tangem/tap/domain/tasks/ScanNoteTask.kt index b2b415dc15..274f14bfa5 100644 --- a/app/src/main/java/com/tangem/tap/domain/tasks/ScanNoteTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/tasks/ScanNoteTask.kt @@ -117,8 +117,17 @@ class ScanNoteTask(val card: Card? = null) : CardSessionRunnable { private fun getErrorIfExcludedCard(card: Card): TangemError? { if (card.isExcluded()) return TapSdkError.CardForDifferentApp + // Disable new cards on the old version of the app // TODO: remove when cards are supported + if (card.isMultiCurrencyWallet() || card.isNote()) return UpdateAppToUseThisCard() // Disable new multi-currency HD wallet cards on the old version of the app // if (card.isMultiCurrencyWallet()) return UpdateAppToUseThisCard() return null } + + private fun getWalletManagerFactory(): WalletManagerFactory { + val blockchainSdkConfig = store.state.globalState.configManager?.config + ?.blockchainSdkConfig ?: BlockchainSdkConfig() + return WalletManagerFactory(blockchainSdkConfig) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt index 826e57090b..966fe4f1d1 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt @@ -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 { override fun run(session: CardSession, callback: (result: CompletionResult) -> 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) { diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt index d2d8aa143c..b951b725bf 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinCardsManager.kt @@ -21,8 +21,6 @@ import com.tangem.tap.tangemSdkManager class TwinCardsManager(private val scanResponse: ScanResponse, context: Context) { private val currentCardId: String = scanResponse.card.cardId -// private val secondCardId: String? = TwinsHelper.getTwinsCardId(currentCardId) - private val secondCardId: String? = null private var currentCardPublicKey: String? = null private var secondCardPublicKey: String? = null @@ -60,13 +58,15 @@ class TwinCardsManager(private val scanResponse: ScanResponse, context: 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 -> { @@ -116,6 +116,14 @@ class TwinCardsManager(private val scanResponse: ScanResponse, context: Context) return CryptoUtils.verify(cardWalletPublicKey, publicKey, signedKey) } + fun verifyTwinPublicKey(issuerData: ByteArray, cardWalletPublicKey: ByteArray?): Boolean { + if (issuerData.size < 65) return false + val publicKey = issuerData.sliceArray(0 until 65) + val signedKey = issuerData.sliceArray(65 until issuerData.size) + return (cardWalletPublicKey != null && + CryptoUtils.verify(cardWalletPublicKey, publicKey, signedKey)) + } + private fun getIssuerKeys(context: Context, publicKey: String): KeyPair { val issuer = getIssuers(context).first { it.publicKey == publicKey } return KeyPair( diff --git a/app/src/main/java/com/tangem/tap/domain/twins/TwinsHelper.kt b/app/src/main/java/com/tangem/tap/domain/twins/TwinsHelper.kt index 65c4d7cb53..ebcbb5ff2b 100644 --- a/app/src/main/java/com/tangem/tap/domain/twins/TwinsHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/twins/TwinsHelper.kt @@ -20,6 +20,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 getTwinCardIdForUser(cardId: String): String { if (cardId.length < 16) return cardId diff --git a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt index 5ebfb1cb14..e2ac447999 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt @@ -61,7 +61,7 @@ class WalletConnectSdkHelper { val decimals = blockchain.decimals() - val value = transaction.value?.hexToBigDecimal() + val value = (transaction.value ?: "0").hexToBigDecimal() ?.movePointLeft(decimals) ?: return null val gasPrice = transaction.gasPrice?.hexToBigDecimal() diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index 4e45d765d7..b22f25959e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt @@ -170,12 +170,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 @@ -187,7 +191,12 @@ private fun prepareAllowedSecurityOptions( ): EnumSet { val prohibitDefaultPin = card?.settings?.isResettingUserCodesAllowed != true + 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) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 55e7fb4f66..6fd84ec7cd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -151,8 +151,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() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 6c3db01f3c..d078cd0526 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -199,7 +199,6 @@ data class TradeCryptoAvailability( ) data class TwinCardsState( - val secondCardId: String?, val cardNumber: TwinCardNumber?, val showTwinOnboarding: Boolean, val isCreatingTwinCardsAllowed: Boolean diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TwinsReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TwinsReducer.kt index 79025ca6cc..ad83caca20 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TwinsReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/TwinsReducer.kt @@ -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) ) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/OnboardingTwinsFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/OnboardingTwinsFragment.kt index 6bfd2f28df..7ecd724f9e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/OnboardingTwinsFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/OnboardingTwinsFragment.kt @@ -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 OnboardingTwinsFragment : 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() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index e8f2a250fd..dbd285226f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -94,7 +94,10 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber