From 3be1a1e694768a486100e672c3bdef4622e56407 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 7 May 2020 15:32:17 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../blockchain_demo/BlockchainDemoActivity.kt | 4 +- .../src/main/java/com/tangem/CardSession.kt | 30 +-- .../src/main/java/com/tangem/Config.kt | 5 +- .../java/com/tangem/SessionEnvironment.kt | 3 +- .../src/main/java/com/tangem/TangemSdk.kt | 33 ++-- .../{SessionError.kt => TangemSdkError.kt} | 176 ++++++++++-------- .../com/tangem/commands/CheckWalletCommand.kt | 23 ++- .../main/java/com/tangem/commands/Command.kt | 33 +++- .../tangem/commands/CreateWalletCommand.kt | 41 +++- .../com/tangem/commands/OpenSessionCommand.kt | 4 +- .../com/tangem/commands/PurgeWalletCommand.kt | 37 +++- .../java/com/tangem/commands/ReadCommand.kt | 6 +- .../tangem/commands/ReadIssuerDataCommand.kt | 18 +- .../commands/ReadIssuerExtraDataCommand.kt | 14 +- .../tangem/commands/ReadUserDataCommand.kt | 102 +++++----- .../java/com/tangem/commands/SignCommand.kt | 63 ++++++- .../tangem/commands/WriteIssuerDataCommand.kt | 65 +++++-- .../commands/WriteIssuerExtraDataCommand.kt | 65 ++++++- .../tangem/commands/WriteUserDataCommand.kt | 42 ++++- .../personalization/DepersonalizeCommand.kt | 16 ++ .../personalization/PersonalizeCommand.kt | 17 +- .../entities/CardConfigExtensions.kt | 2 +- .../com/tangem/common/CompletionResult.kt | 4 +- .../java/com/tangem/common/apdu/StatusWord.kt | 16 +- .../java/com/tangem/common/tlv/TlvDecoder.kt | 20 +- .../java/com/tangem/common/tlv/TlvEncoder.kt | 6 +- .../java/com/tangem/tasks/CreateWalletTask.kt | 6 +- .../main/java/com/tangem/tasks/ScanTask.kt | 6 +- .../com/tangem/common/tlv/TlvDecoderTest.kt | 14 +- .../com/tangem/devkit/TestUserDataActivity.kt | 6 +- .../tangem/devkit/ucase/ui/ActionViewModel.kt | 8 +- tangem-sdk-android-config/README.md | 32 ++-- .../tangem/tangem_sdk_new/nfc/NfcReader.kt | 10 +- 33 files changed, 638 insertions(+), 289 deletions(-) rename tangem-core/src/main/java/com/tangem/{SessionError.kt => TangemSdkError.kt} (55%) diff --git a/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt b/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt index 809eb2e976..038c0ea66c 100644 --- a/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt +++ b/blockchain-demo/src/main/java/com/tangem/blockchain_demo/BlockchainDemoActivity.kt @@ -4,8 +4,8 @@ import android.os.Bundle import android.text.Editable import android.widget.Toast import androidx.appcompat.app.AppCompatActivity -import com.tangem.SessionError import com.tangem.TangemSdk +import com.tangem.TangemSdkError import com.tangem.blockchain.common.* import com.tangem.blockchain.extensions.Result import com.tangem.blockchain.extensions.Signer @@ -65,7 +65,7 @@ class BlockchainDemoActivity : AppCompatActivity() { getInfo() } is CompletionResult.Failure -> { - if (result.error !is SessionError.UserCancelled) { + if (result.error !is TangemSdkError.UserCancelled) { handleError(result.error.toString()) } } diff --git a/tangem-core/src/main/java/com/tangem/CardSession.kt b/tangem-core/src/main/java/com/tangem/CardSession.kt index e2cbafb179..34f243fc4f 100644 --- a/tangem-core/src/main/java/com/tangem/CardSession.kt +++ b/tangem-core/src/main/java/com/tangem/CardSession.kt @@ -37,7 +37,7 @@ interface CardSessionRunnable { * @property viewDelegate is an interface that allows interaction with users and shows relevant UI. * @property cardId ID, Unique Tangem card ID number. If not null, the SDK will check that you the card * with which you tapped a phone has this [cardId] and SDK will return - * the [SessionError.WrongCard] otherwise. + * the [TangemSdkError.WrongCard] otherwise. * @property initialMessage A custom description that will be shown at the beginning of the NFC session. * If null, a default header and text body will be used. */ @@ -86,12 +86,12 @@ class CardSession( /** * Starts a card session and performs preflight [ReadCommand]. - * @param callback: callback with the card session. Can contain [SessionError] if something goes wrong. + * @param callback: callback with the card session. Can contain [TangemSdkError] if something goes wrong. */ - fun start(callback: (session: CardSession, error: SessionError?) -> Unit) { + fun start(callback: (session: CardSession, error: TangemSdkError?) -> Unit) { try { startSession() - } catch (error: SessionError) { + } catch (error: TangemSdkError) { callback(this, error) } @@ -109,7 +109,7 @@ class CardSession( } private fun startSession() { - if (isBusy) throw SessionError.Busy() + if (isBusy) throw TangemSdkError.Busy() isBusy = true viewDelegate.onNfcSessionStarted(cardId, initialMessage) reader.openSession() @@ -133,14 +133,14 @@ class CardSession( is CompletionResult.Success -> { val receivedCardId = result.data.cardId if (cardId != null && receivedCardId != cardId) { - stopWithError(SessionError.WrongCard()) - callback(CompletionResult.Failure(SessionError.WrongCard())) + stopWithError(TangemSdkError.WrongCard()) + callback(CompletionResult.Failure(TangemSdkError.WrongCard())) return@run } val allowedCardTypes = environment.cardFilter.allowedCardTypes if (!allowedCardTypes.contains(result.data.getType())) { - stopWithError(SessionError.WrongCardType()) - callback(CompletionResult.Failure(SessionError.WrongCardType())) + stopWithError(TangemSdkError.WrongCardType()) + callback(CompletionResult.Failure(TangemSdkError.WrongCardType())) return@run } environment.card = result.data @@ -169,12 +169,12 @@ class CardSession( reader.closeSession() isBusy = false - val errorMessage = if (error is SessionError) { + val errorMessage = if (error is TangemSdkError) { "${error::class.simpleName}: ${error.code}" } else { error.localizedMessage } - if (error !is SessionError.UserCancelled) { + if (error !is TangemSdkError.UserCancelled) { Log.e("tag", "Finishing with error: $errorMessage") viewDelegate.onError(errorMessage) } @@ -185,10 +185,10 @@ class CardSession( } private fun tryHandleError( - error: SessionError, callback: (result: CompletionResult) -> Unit) { + error: TangemSdkError, callback: (result: CompletionResult) -> Unit) { when (error) { - is SessionError.NeedEncryption -> { + is TangemSdkError.NeedEncryption -> { Log.i(tag, "Establishing encryption") when (environment.encryptionMode) { EncryptionMode.NONE -> { @@ -201,12 +201,12 @@ class CardSession( } EncryptionMode.STRONG -> { Log.e(tag, "Encryption doesn't work") - callback(CompletionResult.Failure(SessionError.NeedEncryption())) + callback(CompletionResult.Failure(TangemSdkError.NeedEncryption())) } } return establishEncryption(callback) } - else -> callback(CompletionResult.Failure(SessionError.UnknownError())) + else -> callback(CompletionResult.Failure(TangemSdkError.UnknownError())) } } diff --git a/tangem-core/src/main/java/com/tangem/Config.kt b/tangem-core/src/main/java/com/tangem/Config.kt index 20c5c849bd..45da4b6912 100644 --- a/tangem-core/src/main/java/com/tangem/Config.kt +++ b/tangem-core/src/main/java/com/tangem/Config.kt @@ -34,5 +34,8 @@ class Config( /** * Filter that can be used to limit cards that can be interacted with in TangemSdk. */ - val cardFilter: CardFilter = CardFilter() + val cardFilter: CardFilter = CardFilter(), + + var handleErrors: Boolean = true + ) \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt index c1c9a296b2..790a1f7881 100644 --- a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt +++ b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt @@ -21,7 +21,8 @@ data class SessionEnvironment( var encryptionMode: EncryptionMode = EncryptionMode.NONE, var encryptionKey: ByteArray? = null, val cvc: ByteArray? = null, - var cardFilter: CardFilter = CardFilter() + var cardFilter: CardFilter = CardFilter(), + val handleErrors: Boolean ) { fun setPin1(pin1: String) { diff --git a/tangem-core/src/main/java/com/tangem/TangemSdk.kt b/tangem-core/src/main/java/com/tangem/TangemSdk.kt index a5f90dc0ca..8fc1fb4e2e 100644 --- a/tangem-core/src/main/java/com/tangem/TangemSdk.kt +++ b/tangem-core/src/main/java/com/tangem/TangemSdk.kt @@ -46,7 +46,7 @@ class TangemSdk( * it proves that the wallet owns a private key that corresponds to a public one. * * @param callback is triggered on the completion of the [ScanTask] and provides card response - * in the form of [Card] if the task was performed successfully or [SessionError] in case of an error. + * in the form of [Card] if the task was performed successfully or [TangemSdkError] in case of an error. */ fun scanCard(initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { startSessionWithRunnable(ScanTask(), null, initialMessage, callback) @@ -68,7 +68,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number * @param callback is triggered on the completion of the [SignCommand] and provides card response * in the form of [SignResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun sign(hashes: Array, cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -86,7 +86,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [ReadIssuerDataCommand] and provides * card response in the form of [ReadIssuerDataResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun readIssuerData(cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -105,7 +105,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [ReadIssuerExtraDataCommand] and provides * card response in the form of [ReadIssuerExtraDataResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun readIssuerExtraData(cardId: String, callback: (result: CompletionResult) -> Unit) { @@ -126,7 +126,7 @@ class TangemSdk( * @param issuerDataCounter An optional counter that protect issuer data against replay attack. * @param callback is triggered on the completion of the [WriteIssuerDataCommand] and provides * card response in the form of [WriteIssuerDataResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun writeIssuerData(cardId: String, issuerData: ByteArray, @@ -164,7 +164,7 @@ class TangemSdk( * @param issuerDataCounter An optional counter that protect issuer data against replay attack. * @param callback is triggered on the completion of the [WriteIssuerExtraDataCommand] and provides * card response in the form of [WriteIssuerDataResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun writeIssuerExtraData(cardId: String, issuerData: ByteArray, @@ -224,7 +224,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [ReadUserDataCommand] and provides * card response in the form of [ReadUserDataResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun readUserData(cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -246,7 +246,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [CreateWalletTask] and provides * card response in the form of [CreateWalletResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun createWallet(cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -265,7 +265,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [PurgeWalletCommand] and provides * card response in the form of [PurgeWalletResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun purgeWallet(cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -283,7 +283,7 @@ class TangemSdk( * @param cardId CID, Unique Tangem card ID number. * @param callback is triggered on the completion of the [DepersonalizeCommand] and provides * card response in the form of [DepersonalizeResponse] if the task was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. * */ fun depersonalize(cardId: String, initialMessage: Message? = null, callback: (result: CompletionResult) -> Unit) { @@ -306,7 +306,7 @@ class TangemSdk( * (non-EMV) POS terminal infrastructure and transaction processing back-end. * @param callback is triggered on the completion of the [PersonalizeCommand] and provides * card response in the form of [Card] if the command was performed successfully - * or [SessionError] in case of an error. + * or [TangemSdkError] in case of an error. */ fun personalize(config: CardConfig, issuer: Issuer, manufacturer: Manufacturer, acquirer: Acquirer? = null, @@ -325,7 +325,7 @@ class TangemSdk( * @runnable: A custom task, adopting [CardSessionRunnable] protocol * @cardId: CID, Unique Tangem card ID number. If not null, the SDK will check that you the card * with which you tapped a phone has this [cardId] and SDK will return - * the [SessionError.WrongCard] otherwise. + * the [TangemSdkError.WrongCard] otherwise. * @initialMessage: A custom description that shows at the beginning of the NFC session. * If null, default message will be used. * @callback: Standard [TangemSdk] callback. @@ -343,14 +343,14 @@ class TangemSdk( * @cardId: CID, Unique Tangem card ID number. If not null, the SDK will check that you the card * with which you tapped a phone has this [cardId] and SDK will return - * the [SessionError.WrongCard] otherwise. + * the [TangemSdkError.WrongCard] otherwise. * @initialMessage: A custom description that shows at the beginning of the NFC session. * If null, default message will be used. - * @callback: At first, you should check that the [SessionError] is not null, + * @callback: At first, you should check that the [TangemSdkError] is not null, * then you can use the [CardSession] to interact with a card. */ fun startSession(cardId: String? = null, initialMessage: Message? = null, - callback: (session: CardSession, error: SessionError?) -> Unit) { + callback: (session: CardSession, error: TangemSdkError?) -> Unit) { val cardSession = CardSession(buildEnvironment(), reader, viewDelegate, cardId, initialMessage) Thread().run { cardSession.start(callback) } } @@ -367,7 +367,8 @@ class TangemSdk( val terminalKeys = if (config.linkedTerminal) terminalKeysService?.getKeys() else null return SessionEnvironment( terminalKeys = terminalKeys, - cardFilter = config.cardFilter + cardFilter = config.cardFilter, + handleErrors = config.handleErrors ) } diff --git a/tangem-core/src/main/java/com/tangem/SessionError.kt b/tangem-core/src/main/java/com/tangem/TangemSdkError.kt similarity index 55% rename from tangem-core/src/main/java/com/tangem/SessionError.kt rename to tangem-core/src/main/java/com/tangem/TangemSdkError.kt index b5f702ceb2..5167aff71f 100644 --- a/tangem-core/src/main/java/com/tangem/SessionError.kt +++ b/tangem-core/src/main/java/com/tangem/TangemSdkError.kt @@ -9,52 +9,42 @@ import com.tangem.tasks.ScanTask * An error class that represent typical errors that may occur when performing Tangem SDK tasks. * Errors are propagated back to the caller in callbacks. */ -sealed class SessionError(val code: Int) : Exception() { +sealed class TangemSdkError(val code: Int) : Exception(code.toString()) { - //Errors in serializing APDU /** - * This error is returned when there [CommandSerializer] cannot deserialize [com.tangem.common.tlv.Tlv] - * (this error is a wrapper around internal [com.tangem.common.tlv.TlvDecoder] errors). + * This error is returned when Android NFC reader loses a tag + * (e.g. a user detaches card from the phone's NFC module) while the NFC session is in progress. */ - class SerializeCommandError : SessionError(1000) + class TagLost : TangemSdkError(10001) - class DeserializeApduFailed : SessionError(1001) - class EncodingFailedTypeMismatch : SessionError(1002) - class EncodingFailed : SessionError(1003) - class DecodingFailedMissingTag : SessionError(1004) - class DecodingFailedTypeMismatch : SessionError(1005) - class DecodingFailed : SessionError(1005) + class SerializeCommandError : TangemSdkError(20001) + class DeserializeApduFailed : TangemSdkError(20002) + class EncodingFailedTypeMismatch : TangemSdkError(20003) + class EncodingFailed : TangemSdkError(20004) + class DecodingFailedMissingTag : TangemSdkError(20005) + class DecodingFailedTypeMismatch : TangemSdkError(20006) + class DecodingFailed : TangemSdkError(20007) /** * This error is returned when unknown [StatusWord] is received from a card. */ - class UnknownStatus : SessionError(2001) - + class UnknownStatus : TangemSdkError(30001) /** * This error is returned when a card's reply is [StatusWord.ErrorProcessingCommand]. * The card sends this status in case of internal card error. */ - class ErrorProcessingCommand : SessionError(2002) - - /** - * This error is returned when a task (such as [ScanTask]) requires that [ReadCommand] - * is executed before performing other commands. - */ - class MissingPreflightRead : SessionError(2003) - + class ErrorProcessingCommand : TangemSdkError(30002) /** * This error is returned when a card's reply is [StatusWord.InvalidState]. * The card sends this status when command can not be executed in the current state of a card. */ - class InvalidState : SessionError(2004) - + class InvalidState : TangemSdkError(30003) /** * This error is returned when a card's reply is [StatusWord.InsNotSupported]. * The card sends this status when the card cannot process the [com.tangem.common.apdu.Instruction]. */ - class InsNotSupported : SessionError(2005) - + class InsNotSupported : TangemSdkError(30004) /** * This error is returned when a card's reply is [StatusWord.InvalidParams]. * The card sends this status when there are wrong or not sufficient parameters in TLV request, @@ -62,85 +52,113 @@ sealed class SessionError(val code: Int) : Exception() { * The error may be caused, for example, by wrong parameters of the [Task], [CommandSerializer], * mapping or serialization errors. */ - class InvalidParams : SessionError(2006) - + class InvalidParams : TangemSdkError(30005) /** * This error is returned when a card's reply is [StatusWord.NeedEncryption] * and the encryption was not established by TangemSdk. */ - class NeedEncryption : SessionError(2007) + class NeedEncryption : TangemSdkError(30006) - //Scan errors - /** - * This error is returned when a [Task] checks unsuccessfully either - * a card's ability to sign with its private key, or the validity of issuer data. - */ - class VerificationFailed : SessionError(3000) + class Pin1Changed : TangemSdkError(30007) - /** - * This error is returned when a [ScanTask] returns a [Card] without some of the essential fields. - */ - class CardError : SessionError(3001) + class Pin2Changed : TangemSdkError(30008) + class PinsChanged : TangemSdkError(30009) + + + + //Personalization Errors + class AlreadyPersonalized : TangemSdkError(40101) + + //Depersonalization Errors + class CannotBeDepersonalized : TangemSdkError(40201) + + //Read Errors + class Pin1Required : TangemSdkError(40401) /** * This error is returned when a [Task] expects a user to use a particular card, * and a user tries to use a different card. */ - class WrongCard : SessionError(3002) - - /** - * Tangem cards can sign currently up to 10 hashes during one [com.tangem.commands.SignCommand]. - * This error is returned when a [com.tangem.commands.SignCommand] receives more than 10 hashes to sign. - */ - class TooMuchHashesInOneTransaction : SessionError(3003) - - /** - * This error is returned when a [com.tangem.commands.SignCommand] - * receives only empty hashes for signature. - */ - class EmptyHashes : SessionError(3004) - - /** - * This error is returned when a [com.tangem.commands.SignCommand] - * receives hashes of different lengths for signature. - */ - class HashSizeMustBeEqual : SessionError(3005) - - + class WrongCard : TangemSdkError(40403) /** * This error is returned when a user scans a card of a [com.tangem.common.extensions.CardType] * that is not specified in [Config.allowedCards]. */ - class WrongCardType : SessionError(3006) + class WrongCardType : TangemSdkError(40404) + //CreateWallet Errors + class AlreadyCreated : TangemSdkError(40501) + + //PurgeWallet Errors + class PurgeWalletProhibited : TangemSdkError(40601) + + //SetPin Errors + class Pin1CannotBeChanged : TangemSdkError(40801) + class Pin2CannotBeChanged : TangemSdkError(40802) + class Pin1CannotBeDefault : TangemSdkError(40803) + + //Sign Errors + class NoRemainingSignatures : TangemSdkError(40901) /** - * This error is returned when [com.tangem.TangemSdk] was called with a new [Task], - * while a previous [Task] is still in progress. + * This error is returned when a [com.tangem.commands.SignCommand] + * receives only empty hashes for signature. */ - class Busy : SessionError(4000) - + class EmptyHashes : TangemSdkError(40902) /** - * This error is returned when a user manually closes NFC Reading Bottom Sheet Dialog. + * This error is returned when a [com.tangem.commands.SignCommand] + * receives hashes of different lengths for signature. */ - class UserCancelled : SessionError(4001) - - //NFC errors - class NfcReaderError : SessionError(5002) - + class HashSizeMustBeEqual : TangemSdkError(40903) + class CardIsEmpty : TangemSdkError(40904) + class SignHashesNotAvailable : TangemSdkError(40905) /** - * This error is returned when Android NFC reader loses a tag - * (e.g. a user detaches card from the phone's NFC module) while the NFC session is in progress. + * Tangem cards can sign currently up to 10 hashes during one [com.tangem.commands.SignCommand]. + * This error is returned when a [com.tangem.commands.SignCommand] receives more than 10 hashes to sign. */ - class TagLost : SessionError(5003) + class TooManyhHashesInOneTransaction : TangemSdkError(40906) - class UnknownError : SessionError(6000) - - //Specific Command Errors + //General Errors + class NotPersonalized() : TangemSdkError(40001) + class NotActivated : TangemSdkError(40002) + class CardIsPurged : TangemSdkError(40003) + class Pin2OrCvcRequired : TangemSdkError(40004) + /** + * This error is returned when a [Task] checks unsuccessfully either + * a card's ability to sign with its private key, or the validity of issuer data. + */ + class VerificationFailed : TangemSdkError(40005) + class DataSizeTooLarge : TangemSdkError(40006) /** * This error is returned when [ReadIssuerDataTask] or [ReadIssuerExtraDataTask] expects a counter * (when the card's requires it), but the counter is missing. */ - class MissingCounter : SessionError(7001) + class MissingCounter : TangemSdkError(40007) + class OverwritingDataIsProhibited : TangemSdkError(40008) + class DataCannotBeWritten : TangemSdkError(40009) + class MissingIssuerPubicKey : TangemSdkError(40010) + /** + * This error is returned when a [ScanTask] returns a [Card] without some of the essential fields. + */ + class CardError : TangemSdkError(40011) + + + //SDK Errors + class UnknownError: TangemSdkError(50001) + /** + * This error is returned when a user manually closes NFC Reading Bottom Sheet Dialog. + */ + class UserCancelled: TangemSdkError(50002) + /** + * This error is returned when [com.tangem.TangemSdk] was called with a new [Task], + * while a previous [Task] is still in progress. + */ + class Busy : TangemSdkError(50003) + /** + * This error is returned when a task (such as [ScanTask]) requires that [ReadCommand] + * is executed before performing other commands. + */ + class MissingPreflightRead : TangemSdkError(50004) + + +} - class MissingIssuerPubicKey : SessionError(7002) -} \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt b/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt index 4d9c3a53ff..ab33a2cc3c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/CheckWalletCommand.kt @@ -2,7 +2,7 @@ package com.tangem.commands import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction @@ -49,7 +49,7 @@ class CheckWalletCommand( private val challenge = CryptoUtils.generateRandomBytes(16) override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { - transceive(session) { result -> + super.run(session) { result -> when (result) { is CompletionResult.Failure -> { callback(CompletionResult.Failure(result.error)) @@ -63,13 +63,28 @@ class CheckWalletCommand( if (verified) { callback(CompletionResult.Success(result.data)) } else { - callback(CompletionResult.Failure(SessionError.VerificationFailed())) + callback(CompletionResult.Failure(TangemSdkError.VerificationFailed())) } } } } } + override fun handlePreRunErrors( + session: CardSession, + callback: (result: CompletionResult) -> Unit + ): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + return false + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Pin, environment.pin1) @@ -83,7 +98,7 @@ class CheckWalletCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): CheckWalletResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return CheckWalletResponse( diff --git a/tangem-core/src/main/java/com/tangem/commands/Command.kt b/tangem-core/src/main/java/com/tangem/commands/Command.kt index 225fa97430..a0c28b2ba6 100644 --- a/tangem-core/src/main/java/com/tangem/commands/Command.kt +++ b/tangem-core/src/main/java/com/tangem/commands/Command.kt @@ -5,7 +5,7 @@ import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.ResponseApdu import com.tangem.common.apdu.StatusWord -import com.tangem.common.apdu.toSessionError +import com.tangem.common.apdu.toTangemSdkError import com.tangem.common.extensions.toInt import com.tangem.common.tlv.TlvTag @@ -39,7 +39,26 @@ abstract class Command : CardSessionRunnable { override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { Log.i("Command", "Sending ${this::class.java.simpleName}") - transceive(session, callback) + if (session.environment.handleErrors) { + if (handlePreRunErrors(session, callback)) return + } + transceive(session) { result -> + if (session.environment.handleErrors) { + if (handleResponseErrors(session, result, callback)) return@transceive + } + callback(result) + } + } + + open fun handlePreRunErrors(session: CardSession, + callback: (result: CompletionResult) -> Unit): Boolean { + return false + } + + open fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit): Boolean { + return false } fun transceive(session: CardSession, callback: (result: CompletionResult) -> Unit) { @@ -54,7 +73,7 @@ abstract class Command : CardSessionRunnable { } } } - } catch (error: SessionError) { + } catch (error: TangemSdkError) { callback(CompletionResult.Failure(error)) } } @@ -81,17 +100,17 @@ abstract class Command : CardSessionRunnable { transceiveApdu(apdu, session, callback) } else -> { - val error = responseApdu.statusWord.toSessionError() + val error = responseApdu.statusWord.toTangemSdkError() if (error != null && !tryHandleError(error)) { callback(CompletionResult.Failure(error)) } else { - callback(CompletionResult.Failure(SessionError.UnknownError())) + callback(CompletionResult.Failure(TangemSdkError.UnknownError())) } } } } is CompletionResult.Failure -> - if (result.error is SessionError.TagLost) { + if (result.error is TangemSdkError.TagLost) { session.viewDelegate.onTagLost() } else { callback(CompletionResult.Failure(result.error)) @@ -110,7 +129,7 @@ abstract class Command : CardSessionRunnable { return tlv?.find { it.tag == TlvTag.Pause }?.value?.toInt() } - private fun tryHandleError(error: SessionError): Boolean { + private fun tryHandleError(error: TangemSdkError): Boolean { return false } diff --git a/tangem-core/src/main/java/com/tangem/commands/CreateWalletCommand.kt b/tangem-core/src/main/java/com/tangem/commands/CreateWalletCommand.kt index 089a134702..b5563bd747 100644 --- a/tangem-core/src/main/java/com/tangem/commands/CreateWalletCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/CreateWalletCommand.kt @@ -1,7 +1,9 @@ package com.tangem.commands +import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -37,6 +39,41 @@ class CreateWalletResponse( */ class CreateWalletCommand : Command() { + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (session.environment.card?.status == CardStatus.Purged) { + callback(CompletionResult.Failure(TangemSdkError.CardIsPurged())) + return true + } + if (session.environment.card?.status == CardStatus.Loaded) { + callback(CompletionResult.Failure(TangemSdkError.AlreadyCreated())) + return true + } + return false + } + + override fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit): Boolean { + when (result) { + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.InvalidParams) { + callback(CompletionResult.Failure(TangemSdkError.Pin2OrCvcRequired())) + return true + } + return false + } + else -> return false + } + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Pin, environment.pin1) @@ -51,7 +88,7 @@ class CreateWalletCommand : Command() { override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): CreateWalletResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return CreateWalletResponse( diff --git a/tangem-core/src/main/java/com/tangem/commands/OpenSessionCommand.kt b/tangem-core/src/main/java/com/tangem/commands/OpenSessionCommand.kt index 7484f9d48b..891e28f3c1 100644 --- a/tangem-core/src/main/java/com/tangem/commands/OpenSessionCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/OpenSessionCommand.kt @@ -1,7 +1,7 @@ package com.tangem.commands import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -32,7 +32,7 @@ class OpenSessionCommand(private val sessionKeyA: ByteArray) : Command() { + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (session.environment.card?.settingsMask?.contains(Settings.ProhibitPurgeWallet) == true) { + callback(CompletionResult.Failure(TangemSdkError.PurgeWalletProhibited())) + return true + } + return false + } + + override fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit): Boolean { + when (result) { + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.InvalidParams) { + callback(CompletionResult.Failure(TangemSdkError.Pin2OrCvcRequired())) + return true + } + return false + } + else -> return false + } + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Pin, environment.pin1) @@ -42,7 +75,7 @@ class PurgeWalletCommand : Command() { override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): PurgeWalletResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return PurgeWalletResponse( diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadCommand.kt index e3b5d4ccee..d94ba5de4c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadCommand.kt @@ -1,7 +1,7 @@ package com.tangem.commands import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -132,7 +132,7 @@ data class SettingsMask(val rawValue: Int) { enum class Settings(val code: Int) { IsReusable(0x0001), UseActivation(0x0002), - ForbidPurgeWallet(0x0004), + ProhibitPurgeWallet(0x0004), UseBlock(0x0008), AllowSwapPIN(0x0010), @@ -384,7 +384,7 @@ class ReadCommand : Command() { override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): Card { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadIssuerDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadIssuerDataCommand.kt index 7055bc403f..9b1600c5a7 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadIssuerDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadIssuerDataCommand.kt @@ -2,7 +2,7 @@ package com.tangem.commands import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.common.DefaultIssuerDataVerifier import com.tangem.commands.common.IssuerDataMode import com.tangem.commands.common.IssuerDataToVerify @@ -61,12 +61,12 @@ class ReadIssuerDataCommand( override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) return } val publicKey = issuerPublicKey ?: card.issuerPublicKey if (publicKey == null) { - callback(CompletionResult.Failure(SessionError.MissingIssuerPubicKey())) + callback(CompletionResult.Failure(TangemSdkError.MissingIssuerPubicKey())) return } super.run(session) { result -> @@ -83,13 +83,21 @@ class ReadIssuerDataCommand( if (verify(publicKey, result.data.issuerDataSignature, issuerDataToVerify)) { callback(result) } else { - callback(CompletionResult.Failure(SessionError.VerificationFailed())) + callback(CompletionResult.Failure(TangemSdkError.VerificationFailed())) } } } } } + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + return false + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.Pin, environment.pin1) @@ -103,7 +111,7 @@ class ReadIssuerDataCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): ReadIssuerDataResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return ReadIssuerDataResponse( diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadIssuerExtraDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadIssuerExtraDataCommand.kt index db748d8ec5..82e148a05d 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadIssuerExtraDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadIssuerExtraDataCommand.kt @@ -2,7 +2,7 @@ package com.tangem.commands import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.common.DefaultIssuerDataVerifier import com.tangem.commands.common.IssuerDataMode import com.tangem.commands.common.IssuerDataToVerify @@ -71,12 +71,16 @@ class ReadIssuerExtraDataCommand( override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) return } val publicKey = issuerPublicKey ?: card.issuerPublicKey if (publicKey == null) { - callback(CompletionResult.Failure(SessionError.MissingIssuerPubicKey())) + callback(CompletionResult.Failure(TangemSdkError.MissingIssuerPubicKey())) + return + } + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) return } @@ -138,7 +142,7 @@ class ReadIssuerExtraDataCommand( ) callback(CompletionResult.Success(finalResult)) } else { - callback(CompletionResult.Failure(SessionError.VerificationFailed())) + callback(CompletionResult.Failure(TangemSdkError.VerificationFailed())) } } @@ -156,7 +160,7 @@ class ReadIssuerExtraDataCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): ReadIssuerExtraDataResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) diff --git a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt index 528ba98fb0..e3cf00b130 100644 --- a/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/ReadUserDataCommand.kt @@ -1,7 +1,9 @@ package com.tangem.commands +import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -10,32 +12,32 @@ import com.tangem.common.tlv.TlvDecoder import com.tangem.common.tlv.TlvTag class ReadUserDataResponse( - /** - * CID, Unique Tangem card ID number. - */ - val cardId: String, + /** + * CID, Unique Tangem card ID number. + */ + val cardId: String, - /** - * Data defined by user's App. - */ - val userData: ByteArray, + /** + * Data defined by user's App. + */ + val userData: ByteArray, - /** - * Data defined by user's App (confirmed by PIN2). - */ - val userProtectedData: ByteArray, + /** + * Data defined by user's App (confirmed by PIN2). + */ + val userProtectedData: ByteArray, - /** - * Counter initialized by user's App and increased on every signing of new transaction - */ - val userCounter: Int, + /** + * Counter initialized by user's App and increased on every signing of new transaction + */ + val userCounter: Int, - /** - * Counter initialized by user's App (confirmed by PIN2) and increased on every signing of new transaction - */ - val userProtectedCounter: Int + /** + * Counter initialized by user's App (confirmed by PIN2) and increased on every signing of new transaction + */ + val userProtectedCounter: Int -): CommandResponse +) : CommandResponse /** * This command returns two up to 512-byte User_Data, User_Protected_Data and two counters User_Counter and @@ -47,30 +49,42 @@ class ReadUserDataResponse( * of new transaction (on SIGN command that calculate new signatures). The App defines purpose of use. * For example, this fields may contain blockchain nonce value. */ -class ReadUserDataCommand: Command() { +class ReadUserDataCommand : Command() { - override fun serialize(environment: SessionEnvironment): CommandApdu { - val builder = TlvBuilder() - builder.append(TlvTag.CardId, environment.card?.cardId) - builder.append(TlvTag.Pin, environment.pin1) + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + return false + } - return CommandApdu( - Instruction.ReadUserData, builder.serialize(), - environment.encryptionMode, environment.encryptionKey - ) - } + override fun serialize(environment: SessionEnvironment): CommandApdu { + val builder = TlvBuilder() + builder.append(TlvTag.CardId, environment.card?.cardId) + builder.append(TlvTag.Pin, environment.pin1) - override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): ReadUserDataResponse { - val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + return CommandApdu( + Instruction.ReadUserData, builder.serialize(), + environment.encryptionMode, environment.encryptionKey + ) + } - val decoder = TlvDecoder(tlvData) - return ReadUserDataResponse( - cardId = decoder.decode(TlvTag.CardId), - userData = decoder.decode(TlvTag.UserData), - userProtectedData = decoder.decode(TlvTag.UserProtectedData), - userCounter = decoder.decode(TlvTag.UserCounter), - userProtectedCounter = decoder.decode(TlvTag.UserProtectedCounter) - ) - } + override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): ReadUserDataResponse { + val tlvData = apdu.getTlvData(environment.encryptionKey) + ?: throw TangemSdkError.DeserializeApduFailed() + + val decoder = TlvDecoder(tlvData) + return ReadUserDataResponse( + cardId = decoder.decode(TlvTag.CardId), + userData = decoder.decode(TlvTag.UserData), + userProtectedData = decoder.decode(TlvTag.UserProtectedData), + userCounter = decoder.decode(TlvTag.UserCounter), + userProtectedCounter = decoder.decode(TlvTag.UserProtectedCounter) + ) + } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt b/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt index 7707f82197..5c0c5bea32 100644 --- a/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt @@ -1,7 +1,9 @@ package com.tangem.commands +import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -35,6 +37,57 @@ class SignCommand(private val hashes: Array) private val hashSizes = if (hashes.isNotEmpty()) hashes.first().size else 0 + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (session.environment.card?.status == CardStatus.Purged) { + callback(CompletionResult.Failure(TangemSdkError.CardIsPurged())) + return true + } + if (session.environment.card?.status == CardStatus.Empty) { + callback(CompletionResult.Failure(TangemSdkError.CardIsEmpty())) + return true + } + if (session.environment.card?.walletRemainingSignatures == 0) { + callback(CompletionResult.Failure(TangemSdkError.NoRemainingSignatures())) + return true + } + if (session.environment.card?.signingMethods?.contains(SigningMethod.SignHash) != true) { + callback(CompletionResult.Failure(TangemSdkError.SignHashesNotAvailable())) + return true + } + if (hashSizes == 0) { + callback(CompletionResult.Failure(TangemSdkError.EmptyHashes())) + return true + } + if (hashes.any { it.size != hashSizes }) { + callback(CompletionResult.Failure(TangemSdkError.HashSizeMustBeEqual())) + return true + } + return false + } + + override fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit): Boolean { + when (result) { + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.InvalidParams) { + callback(CompletionResult.Failure(TangemSdkError.Pin2OrCvcRequired())) + return true + } + return false + } + else -> return false + } + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val dataToSign = flattenHashes() val tlvBuilder = TlvBuilder() @@ -58,9 +111,9 @@ class SignCommand(private val hashes: Array) } private fun checkForErrors() { - if (hashes.isEmpty()) throw SessionError.EmptyHashes() - if (hashes.size > 10) throw SessionError.TooMuchHashesInOneTransaction() - if (hashes.any { it.size != hashSizes }) throw SessionError.HashSizeMustBeEqual() + if (hashes.isEmpty()) throw TangemSdkError.EmptyHashes() + if (hashes.size > 10) throw TangemSdkError.TooManyhHashesInOneTransaction() + if (hashes.any { it.size != hashSizes }) throw TangemSdkError.HashSizeMustBeEqual() } /** @@ -81,7 +134,7 @@ class SignCommand(private val hashes: Array) override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): SignResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return SignResponse( diff --git a/tangem-core/src/main/java/com/tangem/commands/WriteIssuerDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/WriteIssuerDataCommand.kt index a425f5a740..fa817fd392 100644 --- a/tangem-core/src/main/java/com/tangem/commands/WriteIssuerDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/WriteIssuerDataCommand.kt @@ -2,7 +2,7 @@ package com.tangem.commands import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.common.DefaultIssuerDataVerifier import com.tangem.commands.common.IssuerDataMode import com.tangem.commands.common.IssuerDataToVerify @@ -40,33 +40,62 @@ class WriteIssuerDataCommand( verifier: IssuerDataVerifier = DefaultIssuerDataVerifier() ) : Command(), IssuerDataVerifier by verifier { - override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { - + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) - return + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) + return true } val publicKey = issuerPublicKey ?: card.issuerPublicKey if (publicKey == null) { - callback(CompletionResult.Failure(SessionError.MissingIssuerPubicKey())) - return + callback(CompletionResult.Failure(TangemSdkError.MissingIssuerPubicKey())) + return true + } + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (issuerData.size > MAX_SIZE) { + callback(CompletionResult.Failure(TangemSdkError.DataSizeTooLarge())) + return true } - if (!isCounterValid(issuerDataCounter, card)) { - callback(CompletionResult.Failure(SessionError.MissingCounter())) - } else if (!verifySignature(publicKey, card.cardId)) { - callback(CompletionResult.Failure(SessionError.VerificationFailed())) - } else { - super.run(session, callback) + callback(CompletionResult.Failure(TangemSdkError.MissingCounter())) + return true + } + if (!verifySignature(publicKey, card.cardId)) { + callback(CompletionResult.Failure(TangemSdkError.VerificationFailed())) + return true + } + return false + } + + override fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit + ): Boolean { + when (result) { + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.InvalidParams && + isCounterRequired(session.environment.card)) { + callback(CompletionResult.Failure(TangemSdkError.DataCannotBeWritten())) + return true + } + return false + } + else -> return false } } private fun isCounterValid(issuerDataCounter: Int?, card: Card): Boolean = if (isCounterRequired(card)) issuerDataCounter != null else true - private fun isCounterRequired(card: Card): Boolean = - card.settingsMask?.contains(Settings.ProtectIssuerDataAgainstReplay) != false + private fun isCounterRequired(card: Card?): Boolean = + card?.settingsMask?.contains(Settings.ProtectIssuerDataAgainstReplay) != false private fun verifySignature(publicKey: ByteArray, cardId: String): Boolean { return verify( @@ -93,11 +122,15 @@ class WriteIssuerDataCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): WriteIssuerDataResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return WriteIssuerDataResponse( cardId = decoder.decode(TlvTag.CardId) ) } + + companion object { + const val MAX_SIZE = 512 + } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/WriteIssuerExtraDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/WriteIssuerExtraDataCommand.kt index 4a93ebd734..188273730c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/WriteIssuerExtraDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/WriteIssuerExtraDataCommand.kt @@ -2,7 +2,7 @@ package com.tangem.commands import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.common.DefaultIssuerDataVerifier import com.tangem.commands.common.IssuerDataMode import com.tangem.commands.common.IssuerDataToVerify @@ -46,24 +46,68 @@ class WriteIssuerExtraDataCommand( override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) return } val publicKey = issuerPublicKey ?: card.issuerPublicKey if (publicKey == null) { - callback(CompletionResult.Failure(SessionError.MissingIssuerPubicKey())) + callback(CompletionResult.Failure(TangemSdkError.MissingIssuerPubicKey())) return } - if (!isCounterValid(issuerDataCounter, card)) { - callback(CompletionResult.Failure(SessionError.MissingCounter())) - } else if (!verifySignatures(card.cardId, publicKey)) { - callback(CompletionResult.Failure(SessionError.VerificationFailed())) - } else { - writeIssuerData(session, card.cardId, publicKey, callback) + writeIssuerData(session, card.cardId, publicKey) { response -> + when (response) { + is CompletionResult.Success -> callback(response) + is CompletionResult.Failure -> { + if (response.error is TangemSdkError.InvalidParams && isCounterRequired(card)) { + callback(CompletionResult.Failure(TangemSdkError.DataCannotBeWritten())) + return@writeIssuerData + } + if (response.error is TangemSdkError.InvalidState && + card.settingsMask?.contains(Settings.ProtectIssuerDataAgainstReplay) != false) { + callback(CompletionResult.Failure(TangemSdkError.OverwritingDataIsProhibited())) + return@writeIssuerData + } + } + } } } + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + val card = session.environment.card + if (card == null) { + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) + return true + } + val publicKey = issuerPublicKey ?: card.issuerPublicKey + if (publicKey == null) { + callback(CompletionResult.Failure(TangemSdkError.MissingIssuerPubicKey())) + return true + } + + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (issuerData.size > MAX_SIZE) { + callback(CompletionResult.Failure(TangemSdkError.DataSizeTooLarge())) + return true + } + if (!isCounterValid(issuerDataCounter, card)) { + callback(CompletionResult.Failure(TangemSdkError.MissingCounter())) + return true + } + if (!verifySignatures(card.cardId, publicKey)) { + callback(CompletionResult.Failure(TangemSdkError.VerificationFailed())) + return true + } + return false + } + private fun isCounterValid(issuerDataCounter: Int?, card: Card): Boolean = if (isCounterRequired(card)) issuerDataCounter != null else true @@ -156,7 +200,7 @@ class WriteIssuerExtraDataCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): WriteIssuerDataResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() return WriteIssuerDataResponse(cardId = TlvDecoder(tlvData).decode(TlvTag.CardId) ) @@ -164,5 +208,6 @@ class WriteIssuerExtraDataCommand( companion object { const val SINGLE_WRITE_SIZE = 1524 + const val MAX_SIZE = 32 * 1024 } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt index 7b43e879e7..8e965cded3 100644 --- a/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/WriteUserDataCommand.kt @@ -1,7 +1,9 @@ package com.tangem.commands +import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -32,6 +34,38 @@ class WriteUserDataCommand(private val userData: ByteArray? = null, private val private val userCounter: Int? = null, private val userProtectedCounter: Int? = null) : Command() { + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.isActivated == true) { + callback(CompletionResult.Failure(TangemSdkError.NotActivated())) + return true + } + if (userData?.size ?: 0 > MAX_SIZE || userProtectedData?.size ?: 0 > MAX_SIZE) { + callback(CompletionResult.Failure(TangemSdkError.DataSizeTooLarge())) + return true + } + return false + } + + override fun handleResponseErrors(session: CardSession, + result: CompletionResult, + callback: (result: CompletionResult) -> Unit + ): Boolean { + when (result) { + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.InvalidParams) { + callback(CompletionResult.Failure(TangemSdkError.Pin2OrCvcRequired())) + return true + } + return false + } + else -> return false + } + } + override fun serialize(environment: SessionEnvironment): CommandApdu { val builder = TlvBuilder() builder.append(TlvTag.CardId, environment.card?.cardId) @@ -51,7 +85,11 @@ class WriteUserDataCommand(private val userData: ByteArray? = null, private val override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): WriteUserDataResponse { val tlvData = apdu.getTlvData(environment.encryptionKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() return WriteUserDataResponse(TlvDecoder(tlvData).decode(TlvTag.CardId)) } + + companion object{ + const val MAX_SIZE = 512 + } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt index 2ed9366331..ac47de6c75 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/DepersonalizeCommand.kt @@ -1,8 +1,12 @@ package com.tangem.commands.personalization +import com.tangem.CardSession import com.tangem.SessionEnvironment +import com.tangem.TangemSdkError +import com.tangem.commands.CardStatus import com.tangem.commands.Command import com.tangem.commands.CommandResponse +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -17,6 +21,18 @@ data class DepersonalizeResponse(val success: Boolean) : CommandResponse */ class DepersonalizeCommand : Command() { + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status == CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.NotPersonalized())) + return true + } + if (session.environment.card?.firmwareVersion?.contains("SDK") == false) { + callback(CompletionResult.Failure(TangemSdkError.CannotBeDepersonalized())) + return true + } + return false + } + override fun serialize(environment: SessionEnvironment): CommandApdu { return CommandApdu( Instruction.Depersonalize, byteArrayOf() diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt index e4fe1a8b15..b7f2c7c9dc 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/PersonalizeCommand.kt @@ -1,11 +1,14 @@ package com.tangem.commands.personalization +import com.tangem.CardSession import com.tangem.SessionEnvironment -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.Card import com.tangem.commands.CardData +import com.tangem.commands.CardStatus import com.tangem.commands.Command import com.tangem.commands.personalization.entities.* +import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.Instruction import com.tangem.common.apdu.ResponseApdu @@ -36,6 +39,14 @@ class PersonalizeCommand( private val acquirer: Acquirer? = null ) : Command() { + override fun handlePreRunErrors(session: CardSession, callback: (result: CompletionResult) -> Unit): Boolean { + if (session.environment.card?.status != CardStatus.NotPersonalized) { + callback(CompletionResult.Failure(TangemSdkError.AlreadyPersonalized())) + return true + } + return false + } + override fun serialize(environment: SessionEnvironment): CommandApdu { return CommandApdu( Instruction.Personalize, @@ -46,7 +57,7 @@ class PersonalizeCommand( override fun deserialize(environment: SessionEnvironment, apdu: ResponseApdu): Card { val tlvData = apdu.getTlvData(devPersonalizationKey) - ?: throw SessionError.DeserializeApduFailed() + ?: throw TangemSdkError.DeserializeApduFailed() val decoder = TlvDecoder(tlvData) return Card( @@ -99,7 +110,7 @@ class PersonalizeCommand( } private fun serializePersonalizationData(config: CardConfig): ByteArray { - val cardId = config.createCardId() ?: throw SessionError.SerializeCommandError() + val cardId = config.createCardId() ?: throw TangemSdkError.SerializeCommandError() val tlvBuilder = TlvBuilder() tlvBuilder.append(TlvTag.CardId, cardId) diff --git a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt index 4d7895f3c4..78e5709596 100644 --- a/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt +++ b/tangem-core/src/main/java/com/tangem/commands/personalization/entities/CardConfigExtensions.kt @@ -29,7 +29,7 @@ internal fun CardConfig.createSettingsMask(): SettingsMask { if (protectIssuerDataAgainstReplay) builder.add(Settings.ProtectIssuerDataAgainstReplay) - if (forbidPurgeWallet) builder.add(Settings.ForbidPurgeWallet) + if (forbidPurgeWallet) builder.add(Settings.ProhibitPurgeWallet) if (allowSelectBlockchain) builder.add(Settings.AllowSelectBlockchain) if (skipCheckPIN2andCVCIfValidatedByIssuer) builder.add(Settings.SkipCheckPin2andCvcIfValidatedByIssuer) diff --git a/tangem-core/src/main/java/com/tangem/common/CompletionResult.kt b/tangem-core/src/main/java/com/tangem/common/CompletionResult.kt index 71f460c7d7..52bf7a9351 100644 --- a/tangem-core/src/main/java/com/tangem/common/CompletionResult.kt +++ b/tangem-core/src/main/java/com/tangem/common/CompletionResult.kt @@ -1,6 +1,6 @@ package com.tangem.common -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.common.CompletionResult.Success /** @@ -9,5 +9,5 @@ import com.tangem.common.CompletionResult.Success */ sealed class CompletionResult { class Success(val data: T) : CompletionResult() - class Failure(val error: SessionError) : CompletionResult() + class Failure(val error: TangemSdkError) : CompletionResult() } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt index 3938cee65f..96daaa2826 100644 --- a/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt +++ b/tangem-core/src/main/java/com/tangem/common/apdu/StatusWord.kt @@ -1,6 +1,6 @@ package com.tangem.common.apdu -import com.tangem.SessionError +import com.tangem.TangemSdkError /** * Part of a response from the card, shows the status of the operation @@ -25,16 +25,16 @@ enum class StatusWord(val code: Int, val description: String) { } } -fun StatusWord.toSessionError(): SessionError? { +fun StatusWord.toTangemSdkError(): TangemSdkError? { return when (this) { StatusWord.ProcessCompleted, StatusWord.Pin1Changed, StatusWord.Pin2Changed, StatusWord.PinsChanged -> null StatusWord.NeedPause -> null - StatusWord.InvalidParams -> SessionError.InvalidParams() - StatusWord.ErrorProcessingCommand -> SessionError.ErrorProcessingCommand() - StatusWord.InvalidState -> SessionError.InvalidState() - StatusWord.InsNotSupported -> SessionError.InsNotSupported() - StatusWord.NeedEncryption -> SessionError.NeedEncryption() - StatusWord.Unknown -> SessionError.UnknownStatus() + StatusWord.InvalidParams -> TangemSdkError.InvalidParams() + StatusWord.ErrorProcessingCommand -> TangemSdkError.ErrorProcessingCommand() + StatusWord.InvalidState -> TangemSdkError.InvalidState() + StatusWord.InsNotSupported -> TangemSdkError.InsNotSupported() + StatusWord.NeedEncryption -> TangemSdkError.NeedEncryption() + StatusWord.Unknown -> TangemSdkError.UnknownStatus() } } diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvDecoder.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvDecoder.kt index 4954c38c46..2b9bd3520c 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvDecoder.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvDecoder.kt @@ -1,7 +1,7 @@ package com.tangem.common.tlv import com.tangem.Log -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.* import com.tangem.commands.common.IssuerDataMode import com.tangem.common.extensions.toDate @@ -34,7 +34,7 @@ class TlvDecoder(val tlvList: List) { inline fun decodeOptional(tag: TlvTag): T? = try { decode(tag) - } catch (exception: SessionError.DecodingFailedMissingTag) { + } catch (exception: TangemSdkError.DecodingFailedMissingTag) { null } @@ -55,7 +55,7 @@ class TlvDecoder(val tlvList: List) { return false as T } else { Log.e(this::class.simpleName!!, "Tag $tag not found") - throw SessionError.DecodingFailedMissingTag() + throw TangemSdkError.DecodingFailedMissingTag() } return when (tag.valueType()) { @@ -73,7 +73,7 @@ class TlvDecoder(val tlvList: List) { tlvValue.toInt() as T } catch (exception: IllegalArgumentException) { Log.e(this::class.simpleName!!, exception.message ?: "") - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } } TlvValueType.BoolValue -> { @@ -90,7 +90,7 @@ class TlvDecoder(val tlvList: List) { EllipticCurve.byName(tlvValue.toUtf8()) as T } catch (exception: Exception) { logException(tag, tlvValue.toUtf8(), exception) - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } @@ -101,7 +101,7 @@ class TlvDecoder(val tlvList: List) { tlvValue.toDate() as T } catch (exception: Exception) { logException(tag, tlvValue.toHexString(), exception) - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } } TlvValueType.ProductMask -> { @@ -118,7 +118,7 @@ class TlvDecoder(val tlvList: List) { CardStatus.byCode(tlvValue.toInt()) as T } catch (exception: Exception) { logException(tag, tlvValue.toInt().toString(), exception) - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } } TlvValueType.SigningMethod -> { @@ -127,7 +127,7 @@ class TlvDecoder(val tlvList: List) { SigningMethodMask(tlvValue.toInt()) as T } catch (exception: Exception) { logException(tag, tlvValue.toInt().toString(), exception) - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } } TlvValueType.IssuerDataMode -> { @@ -136,7 +136,7 @@ class TlvDecoder(val tlvList: List) { IssuerDataMode.byCode(tlvValue.toInt().toByte()) as T } catch (exception: Exception) { logException(tag, tlvValue.toInt().toString(), exception) - throw SessionError.DecodingFailed() + throw TangemSdkError.DecodingFailed() } } } @@ -151,7 +151,7 @@ class TlvDecoder(val tlvList: List) { if (T::class != ExpectedT::class) { Log.e(this::class.simpleName!!, "Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - throw SessionError.DecodingFailedTypeMismatch() + throw TangemSdkError.DecodingFailedTypeMismatch() } } diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvEncoder.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvEncoder.kt index 057b0807e8..99589b7d40 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvEncoder.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvEncoder.kt @@ -1,7 +1,7 @@ package com.tangem.common.tlv import com.tangem.Log -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.* import com.tangem.commands.common.IssuerDataMode import com.tangem.common.extensions.calculateSha256 @@ -24,7 +24,7 @@ class TlvEncoder { return Tlv(tag, encodeValue(tag, value)) } else { Log.e(this::class.simpleName!!, "Encoding error. Value for tag $tag is null") - throw SessionError.EncodingFailed() + throw TangemSdkError.EncodingFailed() } } @@ -106,7 +106,7 @@ class TlvEncoder { if (T::class != ExpectedT::class) { Log.e(this::class.simpleName!!, "Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - throw SessionError.EncodingFailedTypeMismatch() + throw TangemSdkError.EncodingFailedTypeMismatch() } } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt b/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt index 6b21be102c..c9b87b4da2 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/CreateWalletTask.kt @@ -2,7 +2,7 @@ package com.tangem.tasks import com.tangem.CardSession import com.tangem.CardSessionRunnable -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.CardStatus import com.tangem.commands.CheckWalletCommand import com.tangem.commands.CreateWalletCommand @@ -14,7 +14,7 @@ class CreateWalletTask : CardSessionRunnable { override fun run(session: CardSession, callback: (result: CompletionResult) -> Unit) { val curve = session.environment.card?.curve if (curve == null) { - callback(CompletionResult.Failure(SessionError.CardError())) + callback(CompletionResult.Failure(TangemSdkError.CardError())) return } @@ -24,7 +24,7 @@ class CreateWalletTask : CardSessionRunnable { is CompletionResult.Failure -> callback(createWalletResult) is CompletionResult.Success -> { if (createWalletResult.data.status != CardStatus.Loaded) { - callback(CompletionResult.Failure(SessionError.UnknownError())) + callback(CompletionResult.Failure(TangemSdkError.UnknownError())) } else { val checkWalletCommand = CheckWalletCommand( curve, createWalletResult.data.walletPublicKey diff --git a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt index 39dea59f0b..db78568806 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt @@ -2,7 +2,7 @@ package com.tangem.tasks import com.tangem.CardSession import com.tangem.CardSessionRunnable -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.* import com.tangem.common.CompletionResult @@ -18,7 +18,7 @@ internal class ScanTask : CardSessionRunnable { val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) } else if (card.cardData?.productMask?.contains(Product.Tag) != false) { callback(CompletionResult.Success(card)) @@ -27,7 +27,7 @@ internal class ScanTask : CardSessionRunnable { callback(CompletionResult.Success(card)) } else if (card.curve == null || card.walletPublicKey == null) { - callback(CompletionResult.Failure(SessionError.CardError())) + callback(CompletionResult.Failure(TangemSdkError.CardError())) } else { val checkWalletCommand = CheckWalletCommand(card.curve, card.walletPublicKey) diff --git a/tangem-core/src/test/java/com/tangem/common/tlv/TlvDecoderTest.kt b/tangem-core/src/test/java/com/tangem/common/tlv/TlvDecoderTest.kt index fbd4514c11..8f7bd0b91e 100644 --- a/tangem-core/src/test/java/com/tangem/common/tlv/TlvDecoderTest.kt +++ b/tangem-core/src/test/java/com/tangem/common/tlv/TlvDecoderTest.kt @@ -1,7 +1,7 @@ package com.tangem.common.tlv import com.google.common.truth.Truth.assertThat -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.commands.* import com.tangem.common.extensions.hexToBytes import org.junit.Test @@ -35,21 +35,21 @@ class TlvDecoderTest { @Test fun `map when value is null throws MissingTagException`() { - assertThrows { + assertThrows { tlvMapper.decode(TlvTag.TokenSymbol) } } @Test fun `map optional to wrong type throws WrongTypeException`() { - assertThrows { + assertThrows { tlvMapper.decodeOptional(TlvTag.CardData) } } @Test fun `map to wrong type throws WrongTypeException`() { - assertThrows { + assertThrows { tlvMapper.decode(TlvTag.CardData) } } @@ -76,7 +76,7 @@ class TlvDecoderTest { .isTrue() assertThat(settingsMask.contains(Settings.UseDynamicNdef)) .isTrue() - assertThat(settingsMask.contains(Settings.ForbidPurgeWallet)) + assertThat(settingsMask.contains(Settings.ProhibitPurgeWallet)) .isFalse() } @@ -134,7 +134,7 @@ class TlvDecoderTest { @Test fun `map Enum with unknown code throws ConversionException error`() { val localMapper = TlvDecoder(listOf(Tlv(TlvTag.CurveId, "test".toByteArray()))) - assertThrows { + assertThrows { localMapper.decode(TlvTag.CurveId) } } @@ -171,7 +171,7 @@ class TlvDecoderTest { @Test fun `map Int with wrong value throws ConversionException`() { val localMapper = TlvDecoder(listOf(Tlv(TlvTag.SignedHashes, byteArrayOf(1, 2, 3, 4, 5)))) - assertThrows { + assertThrows { localMapper.decode(TlvTag.SignedHashes) } } diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/TestUserDataActivity.kt b/tangem-devkit/src/main/java/com/tangem/devkit/TestUserDataActivity.kt index c6124d542f..1fd9eeedb6 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/TestUserDataActivity.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/TestUserDataActivity.kt @@ -6,8 +6,8 @@ import android.widget.CompoundButton import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import com.tangem.SessionEnvironment -import com.tangem.SessionError import com.tangem.TangemSdk +import com.tangem.TangemSdkError import com.tangem.common.CompletionResult import com.tangem.tangem_sdk_new.extensions.init import kotlinx.android.synthetic.main.activity_test_user_data.* @@ -92,8 +92,8 @@ class TestUserDataActivity : AppCompatActivity() { } } - private fun handleError(tv: TextView, error: SessionError) { - if (error is SessionError.UserCancelled) return + private fun handleError(tv: TextView, error: TangemSdkError) { + if (error is TangemSdkError.UserCancelled) return runOnUiThread { tv.text = error::class.simpleName } } diff --git a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/ui/ActionViewModel.kt b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/ui/ActionViewModel.kt index 3c04d86d59..7604a2dd9a 100644 --- a/tangem-devkit/src/main/java/com/tangem/devkit/ucase/ui/ActionViewModel.kt +++ b/tangem-devkit/src/main/java/com/tangem/devkit/ucase/ui/ActionViewModel.kt @@ -4,8 +4,8 @@ import android.view.View import androidx.annotation.UiThread import androidx.lifecycle.* import com.google.gson.Gson -import com.tangem.SessionError import com.tangem.TangemSdk +import com.tangem.TangemSdkError import com.tangem.commands.Card import com.tangem.commands.CommandResponse import com.tangem.common.CompletionResult @@ -133,7 +133,7 @@ class ActionViewModel(private val itemsManager: ItemsManager) : ViewModel(), Lif internal class Notifier(private val vm: ActionViewModel) { - private var notShowedError: SessionError? = null + private var notShowedError: TangemSdkError? = null private val gson: Gson = ResponseJsonConverter().gson fun handleActionResult(result: CompletionResult<*>, list: List) { @@ -163,10 +163,10 @@ internal class Notifier(private val vm: ActionViewModel) { } } - private fun handleError(error: SessionError) { + private fun handleError(error: TangemSdkError) { Log.d(this, "error = $error") when (error) { - is SessionError.UserCancelled -> { + is TangemSdkError.UserCancelled -> { if (notShowedError == null) { vm.seError.postValue("User canceled the action") } else { diff --git a/tangem-sdk-android-config/README.md b/tangem-sdk-android-config/README.md index 5acf8ff48f..9a9fc5efc4 100644 --- a/tangem-sdk-android-config/README.md +++ b/tangem-sdk-android-config/README.md @@ -117,7 +117,7 @@ tangemSdk.scanCard { result -> } } is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -132,7 +132,7 @@ Communication with the card is an asynchronous operation. In order to get a resu `CompletionResult` – this is the sealed class for the results of `CardSessionRunnable`. `Success(val data: T)` is triggered after successful operation and contains a `CommandResponse`. -`Failure(val error: SessionError)` is triggered on error. +`Failure(val error: TangemSdkError)` is triggered on error. #### Sign This method allows you to sign one or multiple hashes. Simultaneous signing of array of hashes in a single SIGN command is required to support Bitcoin-type multi-input blockchains (UTXO). The SIGN command will return a corresponding array of signatures. @@ -143,7 +143,7 @@ tangemSdk.sign( cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -164,7 +164,7 @@ An example of usage (description is available at documentation for `TangemSdk.re tangemSdk.readIssuerData(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -184,7 +184,7 @@ An example of usage (description is available at documentation for `TangemSdk.re tangemSdk.readIssuerExtraData(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -204,7 +204,7 @@ An example of usage (description is available at documentation for `TangemSdk.wr tangemSdk.writeIssuerData(cardId, issuerData, issuerDataSignature, issuerDataCounter) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -225,7 +225,7 @@ An example of usage (description is available at documentation for `TangemSdk.wr ) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -246,7 +246,7 @@ An example of usage (description is available at documentation for `TangemSdk.wr ) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -265,7 +265,7 @@ An example of usage (description is available at documentation for `TangemSdk.re tangemSdk.readUserData(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -284,7 +284,7 @@ An example of usage (description is available at documentation for `TangemSdk.cr tangemSdk.createWallet(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -303,7 +303,7 @@ An example of usage (description is available at documentation for `TangemSdk.pu tangemSdk.purgeWallet(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -323,7 +323,7 @@ An example of usage (description is available at documentation for `TangemSdk.de tangemSdk.depersonalize(cardId) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -342,7 +342,7 @@ An example of usage (description is available at documentation for `TangemSdk.pe tangemSdk.personalize(config, issuer, manufacturer, acquirer) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -383,7 +383,7 @@ To do this, you need to call `tangemSdk.startSession()` method and get a `CardSe SignCommand(createSampleHashes())) {result -> when (result) { is CompletionResult.Failure -> { - if (result.error is SessionError.UserCancelledError) { + if (result.error is TangemSdkError.UserCancelledError) { // Handle case when user cancelled manually } // Handle other errors @@ -410,7 +410,7 @@ class OneTapSignTask(private val hashesToSign: Array) : CardSessionRu val card = session.environment.card if (card == null) { - callback(CompletionResult.Failure(SessionError.MissingPreflightRead())) + callback(CompletionResult.Failure(TangemSdkError.MissingPreflightRead())) } else if (card.cardData?.productMask?.contains(Product.Tag) != false) { callback(CompletionResult.Success(card)) @@ -419,7 +419,7 @@ class OneTapSignTask(private val hashesToSign: Array) : CardSessionRu callback(CompletionResult.Success(card)) } else if (card.curve == null || card.walletPublicKey == null) { - callback(CompletionResult.Failure(SessionError.CardError())) + callback(CompletionResult.Failure(TangemSdkError.CardError())) } else { val signCommand = SignCommand(hashesToSign) diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt index 845dbb2abd..002bf20104 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/nfc/NfcReader.kt @@ -6,7 +6,7 @@ import android.nfc.tech.IsoDep import android.nfc.tech.NfcV import com.tangem.CardReader import com.tangem.Log -import com.tangem.SessionError +import com.tangem.TangemSdkError import com.tangem.common.CompletionResult import com.tangem.common.apdu.CommandApdu import com.tangem.common.apdu.ResponseApdu @@ -38,7 +38,7 @@ class NfcReader : CardReader { // Stops reading and sends failure callback to a task // if reading is cancelled (when user closes nfc bottom sheet dialog). closeSession() - callback?.invoke(CompletionResult.Failure(SessionError.UserCancelled())) + callback?.invoke(CompletionResult.Failure(TangemSdkError.UserCancelled())) } } @@ -67,7 +67,7 @@ class NfcReader : CardReader { private fun transceiveData() { if (readingCancelled) { - callback?.invoke(CompletionResult.Failure(SessionError.UserCancelled())) + callback?.invoke(CompletionResult.Failure(TangemSdkError.UserCancelled())) return } if (data == null) return @@ -76,7 +76,7 @@ class NfcReader : CardReader { try { rawResponse = isoDep?.transceive(data) } catch (exception: TagLostException) { - callback?.invoke(CompletionResult.Failure(SessionError.TagLost())) + callback?.invoke(CompletionResult.Failure(TangemSdkError.TagLost())) isoDep = null return } catch (exception: Exception) { @@ -110,7 +110,7 @@ class NfcReader : CardReader { when (response) { is SlixReadResult.Failure -> { Log.e(this::class.simpleName!!, "${response.exception.message}") - callback?.invoke(CompletionResult.Failure(SessionError.ErrorProcessingCommand())) + callback?.invoke(CompletionResult.Failure(TangemSdkError.ErrorProcessingCommand())) } is SlixReadResult.Success -> { callback?.invoke(CompletionResult.Success(ResponseApdu(response.data)))