Updated on 2026-08-14

This commit is contained in:
Tangem 2019-04-03 13:27:50 +03:00
parent 1c288123ea
commit 052daf6642
6 changed files with 168 additions and 60 deletions

View file

@ -109,7 +109,7 @@
android:theme="@style/AppTheme.NoActionBar" />
<activity
android:name="com.tangem.ui.activity.SignTransactionActivity"
android:name="com.tangem.ui.SignTransactionActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.NoActionBar" />

View file

@ -6,6 +6,7 @@ import android.util.Base64;
import android.util.Log;
import com.tangem.App;
import com.tangem.Constant;
import com.tangem.data.local.PendingTransactionsStorage;
import com.tangem.data.network.ServerApiAdalite;
import com.tangem.data.network.model.AdaliteResponse;
@ -23,6 +24,7 @@ import com.tangem.card_common.reader.CardProtocol;
import com.tangem.card_common.tasks.SignTask;
import com.tangem.card_common.util.Util;
import com.tangem.util.DecimalDigitsInputFilter;
import com.tangem.wallet.BuildConfig;
import com.tangem.wallet.R;
import org.spongycastle.crypto.Digest;
@ -198,6 +200,9 @@ public class CardanoEngine extends CoinEngine {
@Override
public boolean checkNewTransactionAmount(Amount amount) {
if( BuildConfig.FLAVOR==Constant.FLAVOR_TANGEM_CARDANO ) {
return true;
}
if (coinData == null) return false;
if (amount.compareTo(convertToAmount(coinData.getBalanceInInternalUnits())) > 0) {
return false;
@ -424,9 +429,10 @@ public class CardanoEngine extends CoinEngine {
final long amountFinal = amount;
final long changeFinal = change;
if (amount + fees > fullAmount) {
throw new CardProtocol.TangemException_WrongAmount(String.format("Balance (%d) < change (%d) + amount (%d)", fullAmount, change, amount));
}
//TODO - uncomment
// if (amount + fees > fullAmount) {
// throw new CardProtocol.TangemException_WrongAmount(String.format("Balance (%d) < change (%d) + amount (%d)", fullAmount, change, amount));
// }
CborBuilder cborBuilder = new CborBuilder();
ArrayBuilder<CborBuilder> txArray = cborBuilder.addArray();

View file

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.tangem.ui.activity.SignTransactionActivity">
tools:context="com.tangem.ui.SignTransactionActivity">
<include
layout="@layout/layout_touch_card"

View file

@ -14,7 +14,7 @@ import android.view.KeyEvent
import android.view.View
import android.widget.Toast
import com.tangem.Constant
import com.tangem.data.Blockchain
import com.tangem.card_android.android.data.PINStorage
import com.tangem.domain.wallet.CoinEngine
import com.tangem.domain.wallet.CoinEngineFactory
import com.tangem.domain.wallet.TangemContext
@ -31,7 +31,6 @@ import java.util.*
import com.tangem.card_android.data.EXTRA_TANGEM_CARD
import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
import com.tangem.ui.activity.PinRequestActivity
import com.tangem.ui.activity.SignTransactionActivity
import kotlinx.android.synthetic.tangemCardano.activity_confirm_transaction.*
class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
@ -52,9 +51,9 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac
nfcManager = NfcManager(this, this)
lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
ctx = TangemContext.loadFromBundle(this, intent.extras)
ctx = TangemContext();//.loadFromBundle(this, intent.extras)
val engine = CoinEngineFactory.create(ctx)
val engine = CoinEngineFactory.createCardano(ctx) //create(ctx)
@Suppress("DEPRECATION") val html = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
Html.fromHtml(engine!!.balanceHTML, Html.FROM_HTML_MODE_LEGACY)
@ -76,17 +75,17 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac
else
tvIncFee.visibility = View.INVISIBLE
if (ctx.card.blockchainID == Blockchain.Token.id) {
// for Blockchain.Token limit decimals
etAmount.setText(amount.toValueString(ctx.card.tokensDecimal))
} else {
// if (ctx.card.blockchainID == Blockchain.Token.id) {
// // for Blockchain.Token limit decimals
// etAmount.setText(amount.toValueString(ctx.card.tokensDecimal))
// } else {
// for others
etAmount.setText(amount.toValueString())
}
// }
tvCurrency.text = engine.balanceCurrency
tvCurrency2.text = engine.feeCurrency
tvCardID.text = ctx.card.cidDescription
// tvCardID.text = ctx.card.cidDescription
etWallet.setText(intent.getStringExtra(Constant.EXTRA_TARGET_ADDRESS))
btnSend.visibility = View.INVISIBLE
@ -134,7 +133,7 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac
return@setOnClickListener
}
val engineCoin = CoinEngineFactory.create(ctx)
val engineCoin = CoinEngineFactory.createCardano(ctx)
if (engineCoin!!.isNeedCheckNode && !nodeCheck) {
Toast.makeText(baseContext, getString(R.string.cannot_reach_current_active_blockchain_node_try_again), Toast.LENGTH_LONG).show()
@ -144,39 +143,50 @@ class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallbac
val txFee = engineCoin.convertToAmount(etFee.text.toString(), tvCurrency2.text.toString())
val txAmount = engineCoin.convertToAmount(etAmount.text.toString(), tvCurrency.text.toString())
if (!engineCoin.hasBalanceInfo()) {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_check_balance_no_connection_with_blockchain_nodes))
return@setOnClickListener
} else if (!engineCoin.isBalanceNotZero) {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.the_wallet_is_empty))
return@setOnClickListener
} else if (!engineCoin.isExtractPossible) {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.please_wait_for_confirmation_of_incoming_transaction))
return@setOnClickListener
}
if (!engineCoin.checkNewTransactionAmountAndFee(txAmount, txFee, isIncludeFee)) {
finishWithError(Activity.RESULT_CANCELED, getString(R.string.not_enough_funds_on_your_card))
return@setOnClickListener
}
// if (!engineCoin.hasBalanceInfo()) {
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_check_balance_no_connection_with_blockchain_nodes))
// return@setOnClickListener
//
// } else if (!engineCoin.isBalanceNotZero) {
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.the_wallet_is_empty))
// return@setOnClickListener
//
// } else if (!engineCoin.isExtractPossible) {
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.please_wait_for_confirmation_of_incoming_transaction))
// return@setOnClickListener
// }
//
// if (!engineCoin.checkNewTransactionAmountAndFee(txAmount, txFee, isIncludeFee)) {
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.not_enough_funds_on_your_card))
// return@setOnClickListener
// }
requestPIN2Count = 0
val intent = Intent(baseContext, PinRequestActivity::class.java)
intent.putExtra(Constant.EXTRA_MODE, PinRequestActivity.Mode.RequestPIN2.toString())
// val intent = Intent(baseContext, PinRequestActivity::class.java)
// intent.putExtra(Constant.EXTRA_MODE, PinRequestActivity.Mode.RequestPIN2.toString())
// ctx.saveToIntent(intent)
// intent.putExtra(Constant.EXTRA_FEE_INCLUDED, isIncludeFee)
// startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_)
//TODO - PIN2 workaround
PINStorage.setPIN2(PINStorage.getDefaultPIN2())
val intent = Intent(baseContext, SignTransactionActivity::class.java)
ctx.saveToIntent(intent)
intent.putExtra(Constant.EXTRA_TARGET_ADDRESS, etWallet!!.text.toString())
intent.putExtra(Constant.EXTRA_AMOUNT, etAmount.text.toString())
intent.putExtra(Constant.EXTRA_AMOUNT_CURRENCY, tvCurrency.text.toString())
intent.putExtra(Constant.EXTRA_FEE, etFee.text.toString())
intent.putExtra(Constant.EXTRA_FEE_CURRENCY, tvCurrency2.text.toString())
intent.putExtra(Constant.EXTRA_FEE_INCLUDED, isIncludeFee)
startActivityForResult(intent, Constant.REQUEST_CODE_REQUEST_PIN2_)
startActivityForResult(intent, Constant.REQUEST_CODE_SIGN_TRANSACTION)
} else
Toast.makeText(this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
}
val coinEngine = CoinEngineFactory.create(ctx)
progressBar.visibility = View.VISIBLE
coinEngine!!.requestFee(
engine!!.requestFee(
object : CoinEngine.BlockchainRequestsCallbacks {
override fun onComplete(success: Boolean) {
if (success) {

View file

@ -1,4 +1,4 @@
package com.tangem.ui.activity
package com.tangem.ui
import android.app.Activity
import android.content.Intent
@ -29,12 +29,22 @@ import com.tangem.ui.dialog.NoExtendedLengthSupportDialog
import com.tangem.ui.dialog.WaitSecurityDelayDialog
import com.tangem.util.LOG
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.activity_sign_transaction.*
import kotlinx.android.synthetic.main.layout_progress_horizontal.*
import kotlinx.android.synthetic.main.layout_touch_card.*
import com.tangem.card_android.data.asBundle
import com.tangem.card_android.data.EXTRA_TANGEM_CARD
import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
import com.tangem.card_common.data.TangemCard
import com.tangem.card_common.tasks.CustomReadCardTask
import com.tangem.card_common.tasks.OneTouchSignTask
import com.tangem.card_common.util.Log
import com.tangem.data.Blockchain
import com.tangem.domain.wallet.cardano.CardanoData
import com.tangem.ui.activity.MainActivity
import com.tangem.ui.activity.SendTransactionActivity
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtocol.Notifications {
@ -48,7 +58,7 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation
private var signTransactionTask: SignTask? = null
private var task: CustomReadCardTask? = null
private lateinit var amount: CoinEngine.Amount
private lateinit var fee: CoinEngine.Amount
@ -76,18 +86,18 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
isIncludeFee = intent.getBooleanExtra(Constant.EXTRA_FEE_INCLUDED, true)
outAddressStr = intent.getStringExtra(Constant.EXTRA_TARGET_ADDRESS)
tvCardID.text = ctx.card!!.cidDescription
// tvCardID.text = ctx.card!!.cidDescription
progressBar.progressTintList = ColorStateList.valueOf(Color.DKGRAY)
progressBar.visibility = View.INVISIBLE
}
public override fun onPause() {
signTransactionTask?.cancel(true)
task?.cancel(true)
super.onPause()
}
public override fun onStop() {
signTransactionTask?.cancel(true)
task?.cancel(true)
super.onStop()
}
@ -117,15 +127,15 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
// get IsoDep handle and run cardReader thread
val isoDep = IsoDep.get(tag)
val uid = tag.id
val sUID = Util.byteArrayToHexString(uid)
// val sUID = Util.byteArrayToHexString(uid)
if (sUID == ctx.card.uid) {
if (lastReadSuccess)
isoDep.timeout = ctx.card.pauseBeforePIN2 + 5000
else
isoDep.timeout = ctx.card.pauseBeforePIN2 + 65000
// if (sUID == ctx.card.uid){
// if (lastReadSuccess)
// isoDep.timeout = ctx.card.pauseBeforePIN2 + 5000
// else
isoDep.timeout = 65000
val coinEngine = CoinEngineFactory.create(ctx)
val coinEngine=CoinEngineFactory.createCardano(ctx!!)!!
coinEngine?.setOnNeedSendTransaction { tx ->
if (tx != null) {
val intent = Intent(this, SendTransactionActivity::class.java)
@ -134,12 +144,94 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
startActivityForResult(intent, Constant.REQUEST_CODE_SEND_TRANSACTION_)
}
}
val transactionToSign = coinEngine?.constructTransaction(amount, fee, isIncludeFee, outAddressStr)
// val transactionToSign = coinEngine?.constructTransaction(amount, fee, isIncludeFee, outAddressStr)
//
// task = SignTask(ctx.card, NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this, transactionToSign)
// task?.start()
signTransactionTask = SignTask(ctx.card, NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this, transactionToSign)
signTransactionTask?.start()
} else
nfcManager.ignoreTag(isoDep.tag)
val tx: OneTouchSignTask.TransactionToSign = object : OneTouchSignTask.TransactionToSign {
var txToSign: SignTask.TransactionToSign?=null
suspend fun requestBalanceAndUnspentTransactions(): Boolean = suspendCoroutine { cont ->
coinEngine!!.requestBalanceAndUnspentTransactions(object : CoinEngine.BlockchainRequestsCallbacks {
override fun onComplete(success: Boolean?) {
cont.resume(success!!)
}
override fun onProgress() {
}
override fun allowAdvance(): Boolean {
return true
}
})
}
fun initData(card: TangemCard)
{
// if( ctx==null ){
// ctx=TangemContext(card)
// }
if( ctx.card==null ){
ctx.card=card
}
if( ctx.coinData==null ) {
ctx.coinData = CardanoData()
}
if( ctx.coinData.wallet.isNullOrEmpty() ) {
coinEngine!!.defineWallet()
runBlocking { requestBalanceAndUnspentTransactions() }
Log.e(MainActivity.TAG, "requestBalanceAndUnspentTransactions completed")
// coinEngine?.setOnNeedSendTransaction { tx ->
// if (tx != null) {
// val intent = Intent(this@SignTransactionActivity, SendTransactionActivity::class.java)
// ctx!!.saveToIntent(intent)
// intent.putExtra(Constant.EXTRA_TX, tx)
// startActivityForResult(intent, Constant.REQUEST_CODE_SEND_TRANSACTION_)
// }
// }
}
if( txToSign==null ) txToSign=coinEngine!!.constructTransaction(amount,fee,isIncludeFee,outAddressStr)
}
override fun isSigningOnCardSupported(card: TangemCard?): Boolean {
initData(card!!)
return (card?.blockchainID== Blockchain.Cardano.id)and(txToSign!!.isSigningMethodSupported(card?.signingMethod))
}
override fun getHashesToSign(card: TangemCard?): Array<ByteArray> {
initData(card!!)
return txToSign!!.hashesToSign
}
override fun getRawDataToSign(card: TangemCard?): ByteArray {
initData(card!!)
return txToSign!!.rawDataToSign
}
override fun getHashAlgToSign(card: TangemCard?): String {
initData(card!!)
return txToSign!!.hashAlgToSign
}
override fun getIssuerTransactionSignature(card: TangemCard?, dataToSignByIssuer: ByteArray?): ByteArray {
initData(card!!)
return txToSign!!.getIssuerTransactionSignature(dataToSignByIssuer)
}
override fun onSignCompleted(card: TangemCard?, signature: ByteArray?) {
initData(card!!)
txToSign!!.onSignCompleted(signature)
}
}
task = OneTouchSignTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this, tx)
task!!.start()
// } else
// nfcManager.ignoreTag(isoDep.tag)
} catch (e: CardProtocol.TangemException_WrongAmount) {
try {
@ -171,7 +263,7 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
}
override fun onReadFinish(cardProtocol: CardProtocol?) {
signTransactionTask = null
task = null
if (cardProtocol != null) {
if (cardProtocol.error == null) {
rlProgressBar.post { rlProgressBar.visibility = View.GONE }
@ -253,7 +345,7 @@ class SignTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback,
}
override fun onReadCancel() {
signTransactionTask = null
task = null
progressBar?.postDelayed({
try {

View file

@ -38,7 +38,7 @@ public class CustomReadCardTask extends Thread {
// this fields are static to optimize process when need enter pin and scan card again
private static ArrayList<String> lastRead_UnsuccessfullPINs = new ArrayList<>();
private static TangemCard.EncryptionMode lastRead_Encryption = null;
private static String lastRead_UID;
private static String lastRead_UID = "";
public static void resetLastReadInfo() {
lastRead_UID = "";