From 53b89d7ff162de8afb308f0c22c4cfd57a41e588 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 11 Sep 2021 21:25:18 +0300 Subject: [PATCH 01/10] Updated on 2026-08-14 --- app/src/main/assets/features_dev.json | 2 +- .../java/com/tangem/tap/domain/TapWalletManager.kt | 5 ++--- .../tap/domain/twins/CreateSecondTwinWalletTask.kt | 14 +++++++++++++- .../tangem/tap/domain/twins/TwinCardsManager.kt | 10 +++++++--- .../com/tangem/tap/domain/twins/TwinsHelper.kt | 13 +++++++++++++ .../tap/features/wallet/redux/WalletAction.kt | 3 +-- .../tap/features/wallet/redux/WalletState.kt | 1 - .../features/wallet/redux/reducers/TwinsReducer.kt | 3 +-- .../wallet/ui/dialogs/TwinsOnboardingFragment.kt | 8 +++----- 9 files changed, 41 insertions(+), 18 deletions(-) diff --git a/app/src/main/assets/features_dev.json b/app/src/main/assets/features_dev.json index 71561c4c69..82e46b21bf 100644 --- a/app/src/main/assets/features_dev.json +++ b/app/src/main/assets/features_dev.json @@ -2,5 +2,5 @@ "isWalletPayIdEnabled": true, "isSendingToPayIdEnabled": true, "isTopUpEnabled": true, - "isCreatingTwinCardsAllowed": false + "isCreatingTwinCardsAllowed": true } \ No newline at end of file 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 acdc924fd4..a67ec007e0 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -98,11 +98,10 @@ class TapWalletManager { store.dispatch(GlobalAction.SaveScanNoteResponse(data)) 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 )) } } 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 c8e936bcce..457d2f26ce 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 @@ -3,6 +3,7 @@ package com.tangem.tap.domain.twins import com.tangem.CardSession import com.tangem.CardSessionRunnable import com.tangem.Message +import com.tangem.TangemSdkError import com.tangem.commands.wallet.CreateWalletResponse import com.tangem.commands.wallet.PurgeWalletCommand import com.tangem.common.CompletionResult @@ -14,13 +15,24 @@ import com.tangem.tasks.CreateWalletTask class CreateSecondTwinWalletTask( private val firstPublicKey: String, + private val firstCardId: String, private val preparingMessage: Message, private val creatingWalletMessage: Message ) : CardSessionRunnable { override val requiresPin2 = true + + override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { - if (session.environment.card?.getSingleWallet()?.publicKey != null) { + val card = session.environment.card + + if (card?.getSingleWallet()?.publicKey != null) { + + if (!card.cardId.startsWith(TwinsHelper.getPairCardSeries(firstCardId) ?: "")) { + callback(CompletionResult.Failure(TangemSdkError.WrongCardType())) + return + } + session.setInitialMessage(preparingMessage) PurgeWalletCommand(TangemSdkConstants.getDefaultWalletIndex()).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 43d313f8a6..877746f413 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 @@ -14,7 +14,6 @@ import com.tangem.tap.tangemSdkManager class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { private val currentCardId: String = scanNoteResponse.card.cardId - private val secondCardId: String? = TwinsHelper.getTwinsCardId(currentCardId) private var currentCardPublicKey: String? = null private var secondCardPublicKey: String? = null @@ -39,9 +38,14 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { preparingMessage: Message, creatingWalletMessage: Message ): SimpleResult { + val task = CreateSecondTwinWalletTask( + firstPublicKey = currentCardPublicKey!!, + firstCardId = currentCardId, + preparingMessage = preparingMessage, + creatingWalletMessage = creatingWalletMessage + ) val response = tangemSdkManager.runTaskAsync( - CreateSecondTwinWalletTask(currentCardPublicKey!!, preparingMessage, creatingWalletMessage), - secondCardId, initialMessage + task, null, initialMessage ) when (response) { is CompletionResult.Success -> { 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 c534afbec6..68a70fe179 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 @@ -24,6 +24,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 -> { 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 ebfadb5df3..4bd89c024b 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 @@ -6,7 +6,6 @@ import com.tangem.blockchain.common.address.AddressType import com.tangem.commands.common.card.Card import com.tangem.tap.common.redux.ErrorAction import com.tangem.tap.common.redux.NotificationAction -import com.tangem.tap.common.redux.global.CryptoCurrencyName import com.tangem.tap.domain.TapError import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.CardCurrencies @@ -132,7 +131,7 @@ sealed class WalletAction : Action { object ShowOnboarding : TwinsAction() object SetOnboardingShown : TwinsAction() data class SetTwinCard( - val secondCardId: String, val number: TwinCardNumber, + val number: TwinCardNumber, val isCreatingTwinCardsAllowed: Boolean, ) : TwinsAction() } 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 35b301fd50..5cfe80591f 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 @@ -196,7 +196,6 @@ data class TopUpState( ) 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/dialogs/TwinsOnboardingFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/TwinsOnboardingFragment.kt index a20b06aa72..1daec73f5b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/TwinsOnboardingFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/TwinsOnboardingFragment.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 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() From 4aa1a2322911d5e9af219b8caaf9a88081081717 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 11 Sep 2021 22:16:58 +0300 Subject: [PATCH 02/10] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../twins/CreateSecondTwinWalletTask.kt | 14 +++--- .../tap/domain/twins/TwinCardsManager.kt | 48 +++++++++++++++---- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 415eb6e9cc..0cf3af21e6 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 415eb6e9ccfcdc3573391b869adeba433f790087 +Subproject commit 0cf3af21e6f441e6323a1ba127ee7518168797df 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 457d2f26ce..69b8426358 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 @@ -1,9 +1,6 @@ package com.tangem.tap.domain.twins -import com.tangem.CardSession -import com.tangem.CardSessionRunnable -import com.tangem.Message -import com.tangem.TangemSdkError +import com.tangem.* import com.tangem.commands.wallet.CreateWalletResponse import com.tangem.commands.wallet.PurgeWalletCommand import com.tangem.common.CompletionResult @@ -14,10 +11,11 @@ import com.tangem.tap.domain.extensions.getSingleWallet import com.tangem.tasks.CreateWalletTask class CreateSecondTwinWalletTask( - private val firstPublicKey: String, - private val firstCardId: String, - 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 val requiresPin2 = true 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 877746f413..ac8e5da05f 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 @@ -1,5 +1,8 @@ package com.tangem.tap.domain.twins +import android.content.Context +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Types import com.tangem.KeyPair import com.tangem.Message import com.tangem.blockchain.extensions.Result @@ -8,16 +11,22 @@ import com.tangem.common.CompletionResult import com.tangem.common.extensions.hexToBytes import com.tangem.common.extensions.toHexString import com.tangem.crypto.CryptoUtils +import com.tangem.tap.common.extensions.readAssetAsString import com.tangem.tap.domain.tasks.ScanNoteResponse +import com.tangem.tap.network.createMoshi import com.tangem.tap.tangemSdkManager -class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { +class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse, context: Context) { private val currentCardId: String = scanNoteResponse.card.cardId private var currentCardPublicKey: String? = null private var secondCardPublicKey: String? = null + private val issuerKeyPair: KeyPair = getIssuerKeys( + context, scanNoteResponse.card.issuerPublicKey!!.toHexString() + ) + suspend fun createFirstWallet(message: Message): SimpleResult { val response = tangemSdkManager.runTaskAsync( CreateFirstTwinWalletTask(), currentCardId, message @@ -41,6 +50,7 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { val task = CreateSecondTwinWalletTask( firstPublicKey = currentCardPublicKey!!, firstCardId = currentCardId, + issuerKeys = issuerKeyPair, preparingMessage = preparingMessage, creatingWalletMessage = creatingWalletMessage ) @@ -59,7 +69,7 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { suspend fun complete(message: Message): Result { val response = tangemSdkManager.runTaskAsync( - FinalizeTwinTask(secondCardPublicKey!!.hexToBytes(), issuerKeys), + FinalizeTwinTask(secondCardPublicKey!!.hexToBytes(), issuerKeyPair), currentCardId, message ) return when (response) { @@ -69,13 +79,6 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { } companion object { - val issuerKeys = KeyPair( - privateKey = "F9F4C50636C9E6FC65F92655BD5C21C85A5F6A34DCD0F1E75FCEA1980FE242F5".hexToBytes(), - publicKey = ("048196AA4B410AC44A3B9CCE18E7BE226AEA070ACC83A9CF67540F" + - "AC49AF25129F6A538A28AD6341358E3C4F9963064F" + - "7E365372A651D374E5C23CDD37FD099BF2").hexToBytes() - ) - fun verifyTwinPublicKey(issuerData: ByteArray, cardWalletPublicKey: ByteArray?): Boolean { if (issuerData.size < 65) return false val publicKey = issuerData.sliceArray(0 until 65) @@ -83,5 +86,30 @@ class TwinCardsManager(private val scanNoteResponse: ScanNoteResponse) { 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( + publicKey = issuer.publicKey.hexToBytes(), + privateKey = issuer.privateKey.hexToBytes() + ) + } + + private fun getAdapter(): JsonAdapter> { + return createMoshi().adapter( + Types.newParameterizedType(List::class.java, Issuer::class.java) + ) + } + + private fun getIssuers(context: Context): List { + val file = context.readAssetAsString("tangem-app-config/issuers") + return getAdapter().fromJson(file)!! + } } -} \ No newline at end of file +} + +private class Issuer( + val id: String, + val privateKey: String, + val publicKey: String, +) \ No newline at end of file From db7709d86678c78844ea1e558a80acbfb0d24e54 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 6 Sep 2021 16:58:56 +0300 Subject: [PATCH 03/10] Updated on 2026-08-14 --- .../com/tangem/tap/common/extensions/Context.kt | 16 ++++++++++++++++ .../domain/configurable/config/ConfigLoaders.kt | 9 +++------ .../domain/twins/CreateSecondTwinWalletTask.kt | 2 +- .../tap/features/details/redux/DetailsAction.kt | 5 ++++- .../redux/twins/CreateTwinWalletMiddleware.kt | 2 +- .../details/ui/twins/CreateTwinWalletFragment.kt | 11 ++++++----- 6 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/extensions/Context.kt diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Context.kt b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt new file mode 100644 index 0000000000..60345e1ab7 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/extensions/Context.kt @@ -0,0 +1,16 @@ +package com.tangem.tap.common.extensions + +import android.content.Context + +fun Context.readFile(fileName: String): String = + this.openFileInput(fileName).bufferedReader().readText() + +fun Context.rewriteFile(content: String, fileName: String) { + this.openFileOutput(fileName, Context.MODE_PRIVATE).use { + it.write(content.toByteArray(), 0, content.length) + } +} + +fun Context.readAssetAsString(fileName: String): String { + return this.assets.open("$fileName.json").bufferedReader().readText() +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt index a47e8fec1c..4c19bab889 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigLoaders.kt @@ -6,6 +6,7 @@ import com.google.firebase.remoteconfig.ktx.remoteConfig import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.tangem.tap.common.analytics.FirebaseAnalyticsHandler +import com.tangem.tap.common.extensions.readAssetAsString import com.tangem.tap.domain.configurable.Loader import timber.log.Timber @@ -22,8 +23,8 @@ class FeaturesLocalLoader( val featureAdapter: JsonAdapter = moshi.adapter(FeatureModel::class.java) val valuesAdapter: JsonAdapter = moshi.adapter(ConfigValueModel::class.java) - val jsonFeatures = readAssetAsString(Loader.featuresName) - val jsonConfigValues = readAssetAsString(Loader.configValuesName) + val jsonFeatures = context.readAssetAsString(Loader.featuresName) + val jsonConfigValues = context.readAssetAsString(Loader.configValuesName) ConfigModel(featureAdapter.fromJson(jsonFeatures), valuesAdapter.fromJson(jsonConfigValues)) } catch (ex: Exception) { @@ -32,10 +33,6 @@ class FeaturesLocalLoader( } onComplete(config) } - - private fun readAssetAsString(fileName: String): String { - return context.assets.open("$fileName.json").bufferedReader().readText() - } } class FeaturesRemoteLoader( 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 69b8426358..8224293d18 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 @@ -54,7 +54,7 @@ class CreateSecondTwinWalletTask( session.environment.card = session.environment.card?.changeStatusToLoaded() WriteProtectedIssuerDataTask( - firstPublicKey.hexToBytes(), TwinCardsManager.issuerKeys + firstPublicKey.hexToBytes(), issuerKeys ).run(session) { writeResult -> when (writeResult) { is CompletionResult.Success -> callback(result) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt index f37ef1c696..756d836287 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsAction.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.details.redux +import android.content.Context import com.tangem.Message import com.tangem.blockchain.common.Wallet import com.tangem.commands.common.card.Card @@ -62,7 +63,9 @@ sealed class DetailsAction : Action { object Confirm : CreateTwinWalletAction() } - data class LaunchFirstStep(val message: Message) : CreateTwinWalletAction() { + data class LaunchFirstStep( + val message: Message, val context: Context + ) : CreateTwinWalletAction() { object Success : CreateTwinWalletAction() object Failure : CreateTwinWalletAction() } diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/twins/CreateTwinWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/twins/CreateTwinWalletMiddleware.kt index e99f7c7ad6..fa81ea9a18 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/twins/CreateTwinWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/twins/CreateTwinWalletMiddleware.kt @@ -49,7 +49,7 @@ class CreateTwinWalletMiddleware { } is DetailsAction.CreateTwinWalletAction.LaunchFirstStep -> { store.state.globalState.scanNoteResponse?.let { - twinsManager = TwinCardsManager(it) + twinsManager = TwinCardsManager(it, action.context) } scope.launch { val result = twinsManager?.createFirstWallet(action.message) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/twins/CreateTwinWalletFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/twins/CreateTwinWalletFragment.kt index 50d87de052..f8a09c7131 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/twins/CreateTwinWalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/twins/CreateTwinWalletFragment.kt @@ -97,11 +97,12 @@ class CreateTwinWalletFragment : Fragment(R.layout.fragment_details_twin_cards), v_step_3.setBackgroundColor(defaultColor) btn_tap.setOnClickListener { store.dispatch(DetailsAction.CreateTwinWalletAction.LaunchFirstStep( - Message(getString( - R.string.details_twins_recreate_title_format, - twinCardNumberString - ) - ))) + Message(getString( + R.string.details_twins_recreate_title_format, + twinCardNumberString + )), + requireContext() + )) } btn_tap.text = getString(R.string.details_twins_recreate_button_format, twinCardNumber.number.toString()) From 5cbf67c405a2086a2f430620f33c3481c9b003ed Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 15 Sep 2021 09:44:48 +0300 Subject: [PATCH 04/10] Updated on 2026-08-14 --- .../java/com/tangem/tap/features/wallet/ui/WalletFragment.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 f5f61139b1..98c2b0d6fe 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 Date: Tue, 21 Sep 2021 11:17:46 +0300 Subject: [PATCH 05/10] Updated on 2026-08-14 --- .../tap/features/details/redux/DetailsReducer.kt | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) 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 132dbddb18..33c71239fb 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 @@ -175,12 +175,18 @@ 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 + val card = if (state.card?.isTwinCard() == true) { + state.card + } else { + state.card?.copy(isPin1Default = true, isPin2Default = true) + } state.copy( - card = state.card?.copy(isPin1Default = true, isPin2Default = true), + card = card, securityScreenState = state.securityScreenState?.copy( currentOption = state.securityScreenState.selectedOption, - allowedOptions = EnumSet.of(SecurityOption.LongTap) + allowedOptions = card?.let { prepareAllowedSecurityOptions(it) } + ?: EnumSet.of(SecurityOption.LongTap) )) } @@ -194,6 +200,9 @@ private fun prepareAllowedSecurityOptions(card: Card): EnumSet { val isDefaultPin2 = card.isPin2Default != false val allowedSecurityOptions = EnumSet.noneOf(SecurityOption::class.java) + if (card.isTwinCard()) { + allowedSecurityOptions.add(SecurityOption.PassCode) + } if ((isDefaultPin1 && isDefaultPin2) || !prohibitDefaultPin) { allowedSecurityOptions.add(SecurityOption.LongTap) } From 520ac11b5626ef2e5d19c90e7f797005c823845f Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 22 Sep 2021 11:30:27 +0300 Subject: [PATCH 06/10] Updated on 2026-08-14 --- .../features/wallet/redux/middlewares/WalletMiddleware.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 183d55ddda..f1e3d5c0ae 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -105,8 +105,14 @@ class WalletMiddleware { ) when (result) { is CompletionResult.Success -> { + val card = globalState?.scanNoteResponse?.card?.let { + result.data.copy( + isPin1Default = it.isPin1Default, + isPin2Default = it.isPin2Default, + ) + } ?: result.data val scanNoteResponse = - globalState?.scanNoteResponse?.copy(card = result.data) + globalState?.scanNoteResponse?.copy(card = card) scanNoteResponse?.let { globalState.tapWalletManager.onCardScanned(scanNoteResponse) } From 113a1401bbd373b5b215413cd8d63d2282d95aa6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 4 Oct 2021 10:49:27 +0300 Subject: [PATCH 07/10] Updated on 2026-08-14 --- .../main/java/com/tangem/tap/domain/tasks/ScanNoteTask.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 db67d87dff..066158592c 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 @@ -16,6 +16,7 @@ import com.tangem.common.extensions.toHexString 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.isNote import com.tangem.tap.domain.extensions.getSingleWallet import com.tangem.tap.domain.extensions.getStatus import com.tangem.tap.domain.twins.TwinCardsManager @@ -149,8 +150,8 @@ class ScanNoteTask(val card: Card? = null) : CardSessionRunnable Date: Fri, 22 Oct 2021 12:19:51 +0300 Subject: [PATCH 08/10] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../domain/twins/CreateSecondTwinWalletTask.kt | 1 + .../tap/features/details/redux/DetailsReducer.kt | 16 ++++++++-------- .../wallet/redux/middlewares/WalletMiddleware.kt | 8 +------- 4 files changed, 11 insertions(+), 16 deletions(-) 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/twins/CreateSecondTwinWalletTask.kt b/app/src/main/java/com/tangem/tap/domain/twins/CreateSecondTwinWalletTask.kt index bd406430fe..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 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 cfd00ae031..91f7a75152 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 @@ -64,7 +64,6 @@ private fun handlePrepareScreen(action: DetailsAction.PrepareScreen, state: Deta appCurrencyState = AppCurrencyState( action.fiatCurrencyName ), - securityScreenState = SecurityScreenState(currentOption = securityOption), createTwinWalletState = twinsState, cardTermsOfUseUrl = action.cardTou.getUrl(action.card) ) @@ -174,14 +173,15 @@ private fun handleSecurityAction( } is DetailsAction.ManageSecurity.SaveChanges.Success -> { // Setting options to show only LongTap from now on for non-twins - val currentOption = state.securityScreenState?.selectedOption state.copy( - securityScreenState = state.securityScreenState?.copy( - currentOption = currentOption, - allowedOptions = state.card?.let { - prepareAllowedSecurityOptions(it, currentOption) } - ?: 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 diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 153078f584..8a680fcf1c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -108,14 +108,8 @@ class WalletMiddleware { ) when (result) { is CompletionResult.Success -> { - val card = globalState?.scanNoteResponse?.card?.let { - result.data.copy( - isPin1Default = it.isPin1Default, - isPin2Default = it.isPin2Default, - ) - } ?: result.data val scanNoteResponse = - globalState?.scanNoteResponse?.copy(card = card) + globalState?.scanNoteResponse?.copy(card = result.data) scanNoteResponse?.let { globalState.tapWalletManager.onCardScanned(scanNoteResponse) } From 7aea15323a8caea17fb633bd4f55a2f81e047ba8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 22 Oct 2021 15:59:39 +0300 Subject: [PATCH 09/10] Updated on 2026-08-14 --- .../tangem/tap/domain/walletconnect/WalletConnectSdkHelper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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() From 167dae1f7598c53a962b80045814c74619a3e39f Mon Sep 17 00:00:00 2001 From: Tangem Date: Sun, 24 Oct 2021 18:06:07 +0300 Subject: [PATCH 10/10] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../java/com/tangem/tap/domain/tasks/ScanNoteTask.kt | 4 +++- .../com/tangem/tap/domain/twins/TwinCardsManager.kt | 12 +----------- .../tap/features/details/redux/DetailsReducer.kt | 3 +-- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index e80938f7d9..0cf3af21e6 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit e80938f7d9ba378a91ac544a9170597e64afa696 +Subproject commit 0cf3af21e6f441e6323a1ba127ee7518168797df 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 274f14bfa5..43425eab48 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 @@ -1,6 +1,8 @@ package com.tangem.tap.domain.tasks import com.tangem.* +import com.tangem.blockchain.common.BlockchainSdkConfig +import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.common.CompletionResult import com.tangem.common.card.Card import com.tangem.common.card.FirmwareVersion @@ -18,6 +20,7 @@ import com.tangem.tap.domain.extensions.getSingleWallet import com.tangem.tap.domain.tasks.product.ScanResponse import com.tangem.tap.domain.twins.TwinCardsManager import com.tangem.tap.domain.twins.isTangemTwin +import com.tangem.tap.store class ScanNoteTask(val card: Card? = null) : CardSessionRunnable { @@ -118,7 +121,6 @@ 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 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 b951b725bf..faa839cbe6 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 @@ -65,9 +65,7 @@ class TwinCardsManager(private val scanResponse: ScanResponse, context: Context) preparingMessage = preparingMessage, creatingWalletMessage = creatingWalletMessage ) - val response = tangemSdkManager.runTaskAsync( - task, null, initialMessage - ) + val response = tangemSdkManager.runTaskAsync(task, null, initialMessage) when (response) { is CompletionResult.Success -> { secondCardPublicKey = response.data.wallet.publicKey.toHexString() @@ -116,14 +114,6 @@ 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/features/details/redux/DetailsReducer.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsReducer.kt index b22f25959e..d2bb330e40 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 @@ -191,10 +191,9 @@ 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) { + if (card?.isTangemTwin() == true) { allowedSecurityOptions.add(SecurityOption.PassCode) } if ((currentSecurityOption == SecurityOption.LongTap) || !prohibitDefaultPin) {