diff --git a/app/src/main/java/com/tangem/data/Blockchain.java b/app/src/main/java/com/tangem/data/Blockchain.java index 3224ae7da0..b2771a6bb2 100644 --- a/app/src/main/java/com/tangem/data/Blockchain.java +++ b/app/src/main/java/com/tangem/data/Blockchain.java @@ -105,4 +105,25 @@ public enum Blockchain { return getImageResource(); } + public String getUriScheme() { + String scheme = null; + switch (this) { + case Bitcoin: + case BitcoinDual: + scheme = "bitcoin"; + break; + case Ethereum: + case Token: + case TokenEmv: + scheme = "ethereum"; + break; + case Litecoin: + scheme = "litecoin"; + break; + case Ripple: + scheme = "ripple"; + } + return scheme; + } + } diff --git a/app/src/main/java/com/tangem/wallet/CoinEngine.java b/app/src/main/java/com/tangem/wallet/CoinEngine.java index 5fce47c602..edf38cad4c 100644 --- a/app/src/main/java/com/tangem/wallet/CoinEngine.java +++ b/app/src/main/java/com/tangem/wallet/CoinEngine.java @@ -197,10 +197,11 @@ public abstract class CoinEngine { public abstract Uri getShareWalletUri(); public Uri getShareWalletUriEx(){ - if (ctx.getBlockchain() == Blockchain.BitcoinCash) - return getShareWalletUri(); + String scheme = ctx.getBlockchain().getUriScheme(); + if (scheme != null) + return Uri.parse(scheme + ":" + getShareWalletUri()); else - return Uri.parse(ctx.getBlockchain().name().toLowerCase() + ":" + getShareWalletUri().toString()); + return getShareWalletUri(); } public abstract boolean checkNewTransactionAmount(Amount amount); diff --git a/app/src/main/java/com/tangem/wallet/TangemContext.java b/app/src/main/java/com/tangem/wallet/TangemContext.java index 09674de601..9d3c4d5194 100644 --- a/app/src/main/java/com/tangem/wallet/TangemContext.java +++ b/app/src/main/java/com/tangem/wallet/TangemContext.java @@ -68,7 +68,7 @@ public class TangemContext { if (blockchain == Blockchain.NftToken) { return card.getTokenSymbol().substring(4) + "
" + getBlockchain().getOfficialName() + " non-fungible token"; } - if (blockchain == Blockchain.StellarAsset) { + if (blockchain == Blockchain.StellarAsset || blockchain == Blockchain.BinanceAsset) { return card.getTokenSymbol() + "
" + getBlockchain().getOfficialName() + " asset"; } if (blockchain == Blockchain.StellarTag) { diff --git a/app/src/main/java/com/tangem/wallet/binance/BinanceAssetEngine.java b/app/src/main/java/com/tangem/wallet/binance/BinanceAssetEngine.java index f5d4b8aeb7..9e336690a3 100644 --- a/app/src/main/java/com/tangem/wallet/binance/BinanceAssetEngine.java +++ b/app/src/main/java/com/tangem/wallet/binance/BinanceAssetEngine.java @@ -95,7 +95,7 @@ public class BinanceAssetEngine extends CoinEngine { if (assetBalance != null) { return assetBalance.toDescriptionString(getDecimals()) + "
+ " + balance.toDescriptionString(getDecimals()) + " for fee"; } - return balance.toDescriptionString(getDecimals()); + return new Amount(BigDecimal.ZERO, ctx.getCard().tokenSymbol).toDescriptionString(getDecimals()) + "
+ " + balance.toDescriptionString(getDecimals()) + " for fee"; } else { return ""; } @@ -125,7 +125,7 @@ public class BinanceAssetEngine extends CoinEngine { @Override public boolean hasBalanceInfo() { if (coinData == null) return false; - return coinData.hasBalanceInfo(); + return coinData.hasBalanceInfo() || coinData.isError404(); } public boolean isExtractPossible() { @@ -135,6 +135,8 @@ public class BinanceAssetEngine extends CoinEngine { ctx.setMessage(R.string.general_wallet_empty); } else if (awaitingConfirmation()) { ctx.setMessage(R.string.loaded_wallet_message_wait); + } else if (coinData.getBalance() == null || coinData.getBalance().isZero()) { + ctx.setMessage(ctx.getString(R.string.confirm_transaction_error_not_enough_eth_for_fee)); } else { return true; } diff --git a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt b/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt index 48a385a3d8..1b5fa7d2c7 100644 --- a/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt +++ b/app/src/tangemAccess/java/com/tangem/ui/PrepareTransactionFragment.kt @@ -154,17 +154,8 @@ class PrepareTransactionFragment : BaseFragment(), NavigationResultListener, Nfc val schemeSplit = code!!.split(":") when (schemeSplit.size) { 2 -> { - if (ctx.blockchain.officialName.toLowerCase(Locale.ROOT).replace("\\s", "") == schemeSplit[0]) { - val uri = Uri.parse(schemeSplit[1]) - etWallet?.setText(uri.path) -// val amount = uri.getQueryParameter("amount") //TODO: enable after redesign -// if (amount != null) { -// etAmount?.setText(amount) -// rgIncFee.check(R.id.rbFeeOut) -// } - } else if (ctx.blockchain == Blockchain.Ripple && schemeSplit[0] == "ripple") { - val uri = Uri.parse(schemeSplit[1]) - etWallet?.setText(uri.path) + if (schemeSplit[0] == ctx.blockchain.uriScheme) { + etWallet?.setText(schemeSplit[1]) } else { etWallet?.setText(code) } diff --git a/tangem-core/src/main/java/com/tangem/CardSession.kt b/tangem-core/src/main/java/com/tangem/CardSession.kt index 7a01bae614..6021923099 100644 --- a/tangem-core/src/main/java/com/tangem/CardSession.kt +++ b/tangem-core/src/main/java/com/tangem/CardSession.kt @@ -77,7 +77,16 @@ class CardSession( runnable.run(this) { result -> when (result) { is CompletionResult.Success -> stop() - is CompletionResult.Failure -> stopWithError(result.error) + is CompletionResult.Failure -> { + if (result.error is TangemSdkError.ExtendedLengthNotSupported) { + if (session.environment.terminalKeys != null) { + session.environment.terminalKeys = null + startWithRunnable(runnable, callback) + return@run + } + } + stopWithError(result.error) + } } callback(result) } diff --git a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt index e51d5e5d97..5f8734f685 100644 --- a/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt +++ b/tangem-core/src/main/java/com/tangem/SessionEnvironment.kt @@ -17,10 +17,10 @@ data class SessionEnvironment( var pin1: ByteArray = DEFAULT_PIN.calculateSha256(), var pin2: ByteArray = DEFAULT_PIN2.calculateSha256(), var card: Card? = null, - val terminalKeys: KeyPair? = null, + var terminalKeys: KeyPair? = null, var encryptionMode: EncryptionMode = EncryptionMode.NONE, var encryptionKey: ByteArray? = null, - val cvc: ByteArray? = null, + var cvc: ByteArray? = null, var cardFilter: CardFilter = CardFilter(), val handleErrors: Boolean = true ) { diff --git a/tangem-core/src/main/java/com/tangem/TangemSdkError.kt b/tangem-core/src/main/java/com/tangem/TangemSdkError.kt index bf0e5842a8..bcf51d0617 100644 --- a/tangem-core/src/main/java/com/tangem/TangemSdkError.kt +++ b/tangem-core/src/main/java/com/tangem/TangemSdkError.kt @@ -16,6 +16,10 @@ sealed class TangemSdkError(val code: Int) : Exception(code.toString()) { * (e.g. a user detaches card from the phone's NFC module) while the NFC session is in progress. */ class TagLost : TangemSdkError(10001) + /** + * This error is returned when NFC driver on an Android device does not support sending more than 261 bytes. + */ + class ExtendedLengthNotSupported : TangemSdkError(10002) class SerializeCommandError : TangemSdkError(20001) 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 8640e30abc..aa5ce9972e 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 @@ -75,7 +75,7 @@ class NfcReader : CardReader { val rawResponse: ByteArray? try { - Log.i(this::class.simpleName!!, "Sending data to the card") + Log.i(this::class.simpleName!!, "Sending data to the card, size is ${data?.size}") rawResponse = isoDep?.transceive(data) } catch (exception: TagLostException) { callback?.invoke(CompletionResult.Failure(TangemSdkError.TagLost())) @@ -83,6 +83,11 @@ class NfcReader : CardReader { return } catch (exception: Exception) { Log.i(this::class.simpleName!!, exception.localizedMessage ?: "Error tranceiving data") + // The messages of errors can vary on different Android devices, + // but we try to identify it by parsing the message. + if (exception.message?.contains("length") == true) { + callback?.invoke(CompletionResult.Failure(TangemSdkError.ExtendedLengthNotSupported())) + } isoDep = null return }