From d382162befa94594fbb36d430760563edbf40d0f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 11 Feb 2020 16:48:00 +0300 Subject: [PATCH] Updated on 2026-08-14 --- tangem-core/build.gradle | 1 + .../src/main/java/com/tangem/CardManager.kt | 3 +- .../java/com/tangem/CardManagerDelegate.kt | 2 +- .../java/com/tangem/commands/SignCommand.kt | 2 +- .../java/com/tangem/common/tlv/TlvEncoder.kt | 14 ++- .../java/com/tangem/common/tlv/TlvMapper.kt | 102 ++++++++++-------- .../main/java/com/tangem/tasks/ScanTask.kt | 8 +- .../com/tangem/tasks/SingleCommandTask.kt | 4 +- .../src/main/java/com/tangem/tasks/Task.kt | 73 +++++++------ .../com/tangem/common/tlv/TlvMapperTest.kt | 11 +- .../com/tangem/tangemtest/MainActivity.kt | 2 +- .../DefaultCardManagerDelegate.kt | 4 +- .../tangem/tangem_sdk_new/nfc/NfcReader.kt | 9 +- 13 files changed, 136 insertions(+), 99 deletions(-) diff --git a/tangem-core/build.gradle b/tangem-core/build.gradle index a4fdd27949..55701789e1 100644 --- a/tangem-core/build.gradle +++ b/tangem-core/build.gradle @@ -12,6 +12,7 @@ dependencies { implementation 'net.i2p.crypto:eddsa:0.3.0' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.5.2' testImplementation "com.google.truth:truth:1.0" + implementation "org.jetbrains.kotlin:kotlin-reflect:1.3.61" } sourceCompatibility = "8" diff --git a/tangem-core/src/main/java/com/tangem/CardManager.kt b/tangem-core/src/main/java/com/tangem/CardManager.kt index ad9651f6b0..e65d1aa050 100644 --- a/tangem-core/src/main/java/com/tangem/CardManager.kt +++ b/tangem-core/src/main/java/com/tangem/CardManager.kt @@ -76,7 +76,8 @@ class CardManager( if (error is TaskError) { callback(TaskEvent.Completion(error)) } else { - callback(TaskEvent.Completion(TaskError.GenericError(error.message))) + Log.e(this::class.simpleName!!, error.message ?: "") + callback(TaskEvent.Completion(TaskError.UnknownError())) } return } diff --git a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt index 973ced5dd2..da742378a2 100644 --- a/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt +++ b/tangem-core/src/main/java/com/tangem/CardManagerDelegate.kt @@ -35,7 +35,7 @@ interface CardManagerDelegate { /** * It is called when some error occur during NFC session. */ - fun onError(error: TaskError? = null) + fun onError(error: TaskError) /** * It is called when a user is expected to enter pin code. 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 9a473aa9c6..d76722e96c 100644 --- a/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt +++ b/tangem-core/src/main/java/com/tangem/commands/SignCommand.kt @@ -46,7 +46,7 @@ class SignCommand(private val hashes: Array) private fun checkForErrors() { if (hashes.isEmpty()) throw TaskError.EmptyHashes() - if (hashes.size > 10) throw TaskError.TooMuchHashes() + if (hashes.size > 10) throw TaskError.TooMuchHashesInOneTransaction() if (hashes.any { it.size != hashSizes }) throw TaskError.HashSizeMustBeEqual() } 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 3db20cd2eb..561603e335 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,5 +1,6 @@ package com.tangem.common.tlv +import com.tangem.Log import com.tangem.commands.* import com.tangem.common.extensions.* import com.tangem.tasks.TaskError @@ -11,7 +12,8 @@ class TlvEncoder { if (value != null) { return Tlv(tag, encodeValue(value, tag)) } else { - throw TaskError.SerializeCommandError("Encoding error. Value for tag $tag is null") + Log.e(this::class.simpleName!!, "Encoding error. Value for tag $tag is null") + throw TaskError.SerializeCommandError() } } @@ -35,7 +37,8 @@ class TlvEncoder { } TlvValueType.BoolValue -> { typeCheck(tag) - throw ConversionException("Usopported operation: Boolean to ByteArray for tag $tag") + Log.e(this::class.simpleName!!, "Unsupported operation: Boolean to ByteArray for tag $tag") + throw TaskError.ConvertError() } TlvValueType.ByteArray -> { typeCheck(tag) @@ -75,7 +78,10 @@ class TlvEncoder { } private inline fun typeCheck(tag: TlvTag) { - if (T::class != ExpectedT::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + 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 TaskError.WrongType() + } } } \ No newline at end of file diff --git a/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt b/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt index 6171dca7d9..90e218c5fa 100644 --- a/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt +++ b/tangem-core/src/main/java/com/tangem/common/tlv/TlvMapper.kt @@ -1,19 +1,14 @@ package com.tangem.common.tlv +import com.tangem.Log import com.tangem.commands.* import com.tangem.common.extensions.toDate import com.tangem.common.extensions.toHexString import com.tangem.common.extensions.toInt import com.tangem.common.extensions.toUtf8 +import com.tangem.tasks.TaskError import java.util.* - -open class TlvMapperException(message: String?) : Exception(message) - -class MissingTagException(message: String? = null) : TlvMapperException(message) -class WrongTypeException(message: String? = null) : TlvMapperException(message) -class ConversionException(message: String? = null) : TlvMapperException(message) - /** * Maps value fields in [Tlv] from raw [ByteArray] to concrete classes * according to their [TlvTag] and corresponding [TlvValueType]. @@ -33,7 +28,7 @@ class TlvMapper(val tlvList: List) { inline fun mapOptional(tag: TlvTag): T? = try { map(tag) - } catch (exception: MissingTagException) { + } catch (exception: TaskError.MissingTag) { null } @@ -46,85 +41,108 @@ class TlvMapper(val tlvList: List) { * * @return [Tlv] value converted to a nullable type [T]. * - * @throws [MissingTagException] if no [Tlv] is found by the Tag. + * @throws [TaskError.MissingTag] exception if no [Tlv] is found by the Tag. */ inline fun map(tag: TlvTag): T { val tlvValue: ByteArray = tlvList.find { it.tag == tag }?.value ?: if (tag.valueType() == TlvValueType.BoolValue && T::class == Boolean::class) { return false as T } else { - throw MissingTagException("Tag $tag not found") + Log.e(this::class.simpleName!!, "Tag $tag not found") + throw TaskError.MissingTag() } return when (tag.valueType()) { TlvValueType.HexString -> { - if (T::class != String::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) tlvValue.toHexString() as T } TlvValueType.Utf8String -> { - if (T::class != String::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) tlvValue.toUtf8() as T } TlvValueType.IntValue -> { - if (T::class != Integer::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) try { tlvValue.toInt() as T } catch (exception: IllegalArgumentException) { - throw ConversionException(exception.message) + Log.e(this::class.simpleName!!, exception.message ?: "") + throw TaskError.ConvertError() } } TlvValueType.BoolValue -> { - if (T::class != Boolean::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) true as T } TlvValueType.ByteArray -> { - if (T::class != ByteArray::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) tlvValue as T } TlvValueType.EllipticCurve -> { - if (T::class != EllipticCurve::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - EllipticCurve.byName(tlvValue.toUtf8()) as? T - ?: throw ConversionException("Unknown Elliptic Curve value: ${tlvValue.toUtf8()}") + typeCheck(tag) + try { + EllipticCurve.byName(tlvValue.toUtf8()) as T + } catch (exception: Exception) { + logException(tag, tlvValue.toUtf8(), exception) + throw TaskError.ConvertError() + } + + } TlvValueType.DateTime -> { - if (T::class != Date::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) try { tlvValue.toDate() as T } catch (exception: Exception) { - throw ConversionException("Converting to date with the following exception: " + exception.message) + logException(tag, tlvValue.toHexString(), exception) + throw TaskError.ConvertError() } } TlvValueType.ProductMask -> { - if (T::class != ProductMask::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - ProductMask.byCode(tlvValue.first()) as? T - ?: throw ConversionException("Unknown Product Mask Code: ${tlvValue.first()}.") + typeCheck(tag) + try { + ProductMask.byCode(tlvValue.first()) as T + } catch (exception: Exception) { + logException(tag, tlvValue.first().toString(), exception) + throw TaskError.ConvertError() + } } TlvValueType.SettingsMask -> { - if (T::class != SettingsMask::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") + typeCheck(tag) SettingsMask(tlvValue.toInt()) as T } TlvValueType.CardStatus -> { - if (T::class != CardStatus::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - CardStatus.byCode(tlvValue.toInt()) as T - ?: throw ConversionException("Unknown Card Status with code of: ${tlvValue.toInt()}") + typeCheck(tag) + try { + CardStatus.byCode(tlvValue.toInt()) as T + } catch (exception: Exception) { + logException(tag, tlvValue.toInt().toString(), exception) + throw TaskError.ConvertError() + } } TlvValueType.SigningMethod -> { - if (T::class != SigningMethod::class) - throw WrongTypeException("Mapping error. Type for tag: $tag must be ${tag.valueType()}. It is ${T::class}") - SigningMethod(tlvValue.toInt()) as T - ?: throw ConversionException("Unknown Signing Method with code of: ${tlvValue.toInt()}") + typeCheck(tag) + try { + SigningMethod(tlvValue.toInt()) as T + } catch (exception: Exception) { + logException(tag, tlvValue.toInt().toString(), exception) + throw TaskError.ConvertError() + } } } } + fun logException(tag: TlvTag, value: String, exception: Exception) { + Log.e(this::class.simpleName!!, + "Unknown ${tag.name} with value of: value, \n${exception.message}") + } + + inline fun typeCheck(tag: TlvTag) { + 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 TaskError.WrongType() + } + } + } \ No newline at end of file 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 742adc0d3f..90a8629be0 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/ScanTask.kt @@ -35,7 +35,7 @@ internal class ScanTask : Task() { if (currentCard != null) callback(TaskEvent.Event(ScanEvent.OnReadEvent(currentCard))) if (currentCard == null) { - completeNfcSession(true, TaskError.MissingPreflightRead()) + completeNfcSession(TaskError.MissingPreflightRead()) callback(TaskEvent.Completion(TaskError.MissingPreflightRead())) } else if (currentCard.cardData?.productMask == ProductMask.Tag) { @@ -47,7 +47,7 @@ internal class ScanTask : Task() { callback(TaskEvent.Completion()) } else if (currentCard.curve == null || currentCard.walletPublicKey == null) { - completeNfcSession(true, TaskError.CardError()) + completeNfcSession(TaskError.CardError()) callback(TaskEvent.Completion(TaskError.CardError())) } else { @@ -57,8 +57,8 @@ internal class ScanTask : Task() { sendCommand(checkWalletCommand, cardEnvironment) { result -> when (result) { is CompletionResult.Failure -> { - if (result.error !is TaskError.UserCancelledError) { - completeNfcSession(true, result.error) + if (result.error !is TaskError.UserCancelled) { + completeNfcSession(result.error) } callback(TaskEvent.Completion(result.error)) } diff --git a/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt b/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt index 60b0129aad..03efa615f8 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/SingleCommandTask.kt @@ -28,8 +28,8 @@ class SingleCommandTask( callback(TaskEvent.Completion()) } is CompletionResult.Failure -> { - if (result.error !is TaskError.UserCancelledError) { - completeNfcSession(true, result.error) + if (result.error !is TaskError.UserCancelled) { + completeNfcSession(result.error) } callback(TaskEvent.Completion(result.error)) } diff --git a/tangem-core/src/main/java/com/tangem/tasks/Task.kt b/tangem-core/src/main/java/com/tangem/tasks/Task.kt index 9f3bf8b836..2f749238f5 100644 --- a/tangem-core/src/main/java/com/tangem/tasks/Task.kt +++ b/tangem-core/src/main/java/com/tangem/tasks/Task.kt @@ -16,33 +16,41 @@ import com.tangem.common.apdu.StatusWord * 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 TaskError(description: String? = null) : Exception(description) { - class UnknownStatus(sw: Int) : TaskError("Unknown StatusWord: $sw") - class MappingError : TaskError() - class GenericError(description: String? = null) : TaskError(description) - class UserCancelledError() : TaskError() - class Busy() : TaskError() - class TagLost() : TaskError() +sealed class TaskError(val code: Int): Exception() { - class ErrorProcessingCommand(description: String? = null) : TaskError(description) - class InvalidState : TaskError() - class InsNotSupported : TaskError() - class InvalidParams : TaskError() - class NeedEncryption : TaskError() - class NeedPause : TaskError() + //Errors in serializing APDU + class SerializeCommandError: TaskError(1001) + class EncodingError: TaskError(1002) + class MissingTag: TaskError(1003) + class WrongType: TaskError(1004) + class ConvertError: TaskError(1005) - class VefificationFailed : TaskError() - class CardError : TaskError() - class ReaderError() : TaskError() - class SerializeCommandError(description: String? = null) : TaskError(description) + //Card errors + class UnknownStatus: TaskError(2001) + class ErrorProcessingCommand: TaskError(2002) + class MissingPreflightRead: TaskError(2003) + class InvalidState: TaskError(2004) + class InsNotSupported: TaskError(2005) + class InvalidParams: TaskError(2006) + class NeedEncryption: TaskError(2007) - class CardIsMissing() : TaskError() - class EmptyHashes() : TaskError() - class TooMuchHashes() : TaskError() - class HashSizeMustBeEqual() : TaskError() + //Scan errors + class VerificationFailed: TaskError(3000) + class CardError: TaskError(3001) + class WrongCard: TaskError(3002) + class TooMuchHashesInOneTransaction: TaskError(3003) + class EmptyHashes: TaskError(3004) + class HashSizeMustBeEqual: TaskError(3005) - class WrongCard() : TaskError() - class MissingPreflightRead() : TaskError() + class Busy: TaskError(4000) + class UserCancelled: TaskError(4001) + class UnsupportedDevice: TaskError(4002) + + //NFC error + class NfcReaderError: TaskError(5002) + class TagLost: TaskError(5003) + + class UnknownError: TaskError(6000) } /** @@ -100,9 +108,9 @@ abstract class Task { * @param withError True when there is an error * @param taskError The error to be shown by [CardManagerDelegate] */ - protected fun completeNfcSession(withError: Boolean = false, taskError: TaskError? = null) { + protected fun completeNfcSession(taskError: TaskError? = null) { reader?.closeSession() - if (withError) { + if (taskError != null) { delegate?.onError(taskError) } else { delegate?.onNfcSessionCompleted() @@ -153,7 +161,10 @@ abstract class Task { } } StatusWord.InvalidParams -> callback(CompletionResult.Failure(TaskError.InvalidParams())) - StatusWord.Unknown -> callback(CompletionResult.Failure(TaskError.UnknownStatus(result.data.sw))) + StatusWord.Unknown -> { + Log.e(this::class.simpleName!!, "Unknown status error: ${result.data.sw}") + callback(CompletionResult.Failure(TaskError.UnknownStatus())) + } StatusWord.ErrorProcessingCommand -> callback(CompletionResult.Failure(TaskError.ErrorProcessingCommand())) StatusWord.InvalidState -> callback(CompletionResult.Failure(TaskError.InvalidState())) @@ -169,10 +180,10 @@ abstract class Task { } } is CompletionResult.Failure -> - if (result.error is TaskError.TagLost) { + if (result.error == TaskError.TagLost()) { delegate?.onTagLost() - } else if (result.error is TaskError.UserCancelledError) { - callback(CompletionResult.Failure(TaskError.UserCancelledError())) + } else if (result.error is TaskError.UserCancelled) { + callback(CompletionResult.Failure(TaskError.UserCancelled())) reader?.closeSession() } } @@ -184,7 +195,7 @@ abstract class Task { sendCommand(ReadCommand(), environment) { readResult -> when (readResult) { is CompletionResult.Failure -> { - completeNfcSession(true, readResult.error) + completeNfcSession(readResult.error) callback(TaskEvent.Completion(readResult.error)) } is CompletionResult.Success -> { @@ -193,7 +204,7 @@ abstract class Task { securityDelayDuration = readResult.data.pauseBeforePin2 ?: 0 if (environment.cardId != null && environment.cardId != receivedCardId) { - completeNfcSession(true, TaskError.WrongCard()) + completeNfcSession(TaskError.WrongCard()) callback(TaskEvent.Completion(TaskError.WrongCard())) return@sendCommand } diff --git a/tangem-core/src/test/java/com/tangem/common/tlv/TlvMapperTest.kt b/tangem-core/src/test/java/com/tangem/common/tlv/TlvMapperTest.kt index 2c8334e752..bbe41dee8a 100644 --- a/tangem-core/src/test/java/com/tangem/common/tlv/TlvMapperTest.kt +++ b/tangem-core/src/test/java/com/tangem/common/tlv/TlvMapperTest.kt @@ -3,6 +3,7 @@ package com.tangem.common.tlv import com.google.common.truth.Truth.assertThat import com.tangem.commands.* import com.tangem.common.extensions.hexToBytes +import com.tangem.tasks.TaskError import org.junit.Test import org.junit.jupiter.api.assertThrows import java.util.* @@ -34,21 +35,21 @@ class TlvMapperTest { @Test fun `map when value is null throws MissingTagException`() { - assertThrows { + assertThrows { tlvMapper.map(TlvTag.TokenSymbol) } } @Test fun `map optional to wrong type throws WrongTypeException`() { - assertThrows { + assertThrows { tlvMapper.mapOptional(TlvTag.CardData) } } @Test fun `map to wrong type throws WrongTypeException`() { - assertThrows { + assertThrows { tlvMapper.map(TlvTag.CardData) } } @@ -125,7 +126,7 @@ class TlvMapperTest { @Test fun `map Enum with unknown code throws ConversionException error`() { val localMapper = TlvMapper(listOf(Tlv(TlvTag.ProductMask, byteArrayOf(5)))) - assertThrows { + assertThrows { localMapper.map(TlvTag.ProductMask) } } @@ -162,7 +163,7 @@ class TlvMapperTest { @Test fun `map Int with wrong value throws ConversionException`() { val localMapper = TlvMapper(listOf(Tlv(TlvTag.SignedHashes, byteArrayOf(1, 2, 3, 4, 5)))) - assertThrows { + assertThrows { localMapper.map(TlvTag.SignedHashes) } } diff --git a/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt b/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt index 6cd62173e3..739ca2c95a 100644 --- a/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt +++ b/tangem-demo/src/main/java/com/tangem/tangemtest/MainActivity.kt @@ -49,7 +49,7 @@ class MainActivity : AppCompatActivity() { } is TaskEvent.Completion -> { if (taskEvent.error != null) { - if (taskEvent.error is TaskError.UserCancelledError) { + if (taskEvent.error is TaskError.UserCancelled) { // Handle case when user cancelled manually } // Handle other errors diff --git a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt index d390b9ee99..821cec4039 100644 --- a/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt +++ b/tangem-sdk/src/main/java/com/tangem/tangem_sdk_new/DefaultCardManagerDelegate.kt @@ -114,14 +114,14 @@ class DefaultCardManagerDelegate(private val reader: NfcReader) : CardManagerDel postUI(300) { readingDialog?.dismiss() } } - override fun onError(error: TaskError?) { + override fun onError(error: TaskError) { postUI { readingDialog?.lTouchCard?.hide() readingDialog?.flSecurityDelay?.hide() readingDialog?.flCompletion?.hide() readingDialog?.flError?.show() readingDialog?.tvTaskTitle?.text = activity.getText(R.string.dialog_error) - readingDialog?.tvTaskText?.text = if (error != null) error::class.simpleName else "" + readingDialog?.tvTaskText?.text = "${error::class.simpleName}: ${error.code}" } } 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 02518ad5f9..5ba6b11d4b 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 @@ -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(TaskError.UserCancelledError())) + callback?.invoke(CompletionResult.Failure(TaskError.UserCancelled())) } } @@ -67,7 +67,7 @@ class NfcReader : CardReader { private fun transceiveData() { if (readingCancelled) { - callback?.invoke(CompletionResult.Failure(TaskError.UserCancelledError())) + callback?.invoke(CompletionResult.Failure(TaskError.UserCancelled())) return } if (data == null) return @@ -109,9 +109,8 @@ class NfcReader : CardReader { val response = SlixTagReader().transceive(nfcV) when (response) { is SlixReadResult.Failure -> { - callback?.invoke(CompletionResult.Failure( - TaskError.ErrorProcessingCommand(response.exception.message)) - ) + Log.e(this::class.simpleName!!, "${response.exception.message}") + callback?.invoke(CompletionResult.Failure(TaskError.ErrorProcessingCommand())) } is SlixReadResult.Success -> { callback?.invoke(CompletionResult.Success(ResponseApdu(response.data)))