296 lines
No EOL
12 KiB
Kotlin
296 lines
No EOL
12 KiB
Kotlin
package com.tangem.presentation.activity
|
|
|
|
import android.app.Activity
|
|
import android.content.Intent
|
|
import android.nfc.NfcAdapter
|
|
import android.nfc.Tag
|
|
import android.os.Build
|
|
import android.os.Bundle
|
|
import androidx.appcompat.app.AppCompatActivity
|
|
import android.text.Editable
|
|
import android.text.Html
|
|
import android.text.TextWatcher
|
|
import android.view.KeyEvent
|
|
import android.view.View
|
|
import android.widget.Toast
|
|
import com.tangem.Constant
|
|
import com.tangem.data.Blockchain
|
|
import com.tangem.domain.wallet.CoinEngine
|
|
import com.tangem.domain.wallet.CoinEngineFactory
|
|
import com.tangem.domain.wallet.TangemContext
|
|
import com.tangem.presentation.event.TransactionFinishWithError
|
|
import com.tangem.tangemcard.android.nfc.NfcLifecycleObserver
|
|
import com.tangem.tangemcard.android.reader.NfcManager
|
|
import com.tangem.tangemcard.data.loadFromBundle
|
|
import com.tangem.tangemcommon.data.TangemCard
|
|
import com.tangem.util.UtilHelper
|
|
import com.tangem.wallet.R
|
|
import kotlinx.android.synthetic.main.activity_confirm_transaction.*
|
|
import org.greenrobot.eventbus.EventBus
|
|
import java.io.IOException
|
|
import java.util.*
|
|
|
|
class ConfirmTransactionActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|
|
|
private lateinit var nfcManager: NfcManager
|
|
private lateinit var ctx: TangemContext
|
|
private lateinit var amount: CoinEngine.Amount
|
|
|
|
private var isIncludeFee: Boolean = true
|
|
private var requestPIN2Count = 0
|
|
private var nodeCheck = true
|
|
private var dtVerified: Date? = null
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
setContentView(R.layout.activity_confirm_transaction)
|
|
|
|
nfcManager = NfcManager(this, this)
|
|
lifecycle.addObserver(NfcLifecycleObserver(nfcManager))
|
|
|
|
ctx = TangemContext.loadFromBundle(this, intent.extras)
|
|
|
|
val engine = CoinEngineFactory.create(ctx)
|
|
|
|
@Suppress("DEPRECATION") val html = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
|
Html.fromHtml(engine!!.balanceHTML, Html.FROM_HTML_MODE_LEGACY)
|
|
else
|
|
Html.fromHtml(engine!!.balanceHTML)
|
|
tvBalance.text = html
|
|
|
|
isIncludeFee = intent.getBooleanExtra(Constant.EXTRA_FEE_INCLUDED, true)
|
|
|
|
if (isIncludeFee)
|
|
tvIncFee.setText(R.string.including_fee)
|
|
else
|
|
tvIncFee.setText(R.string.not_including_fee)
|
|
|
|
amount = CoinEngine.Amount(intent.getStringExtra(Constant.EXTRA_AMOUNT), intent.getStringExtra(Constant.EXTRA_AMOUNT_CURRENCY))
|
|
|
|
if (engine.allowSelectFeeInclusion())
|
|
tvIncFee.visibility = View.VISIBLE
|
|
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 {
|
|
// for others
|
|
etAmount.setText(amount.toValueString())
|
|
}
|
|
|
|
tvCurrency.text = engine.balanceCurrency
|
|
tvCurrency2.text = engine.feeCurrency
|
|
tvCardID.text = ctx.card.cidDescription
|
|
etWallet.setText(intent.getStringExtra(Constant.EXTRA_TARGET_ADDRESS))
|
|
|
|
btnSend.visibility = View.INVISIBLE
|
|
|
|
if (!engine.allowSelectFeeLevel()) {
|
|
rgFee.visibility = View.INVISIBLE
|
|
}
|
|
|
|
// set listeners
|
|
rgFee.setOnCheckedChangeListener { _, checkedId -> doSetFee(checkedId) }
|
|
etFee.addTextChangedListener(object : TextWatcher {
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
|
|
|
}
|
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
try {
|
|
val eqFee = engine.evaluateFeeEquivalent(etFee!!.text.toString())
|
|
tvFeeEquivalent.text = eqFee
|
|
|
|
if (!ctx.coinData!!.amountEquivalentDescriptionAvailable) {
|
|
tvFeeEquivalent.error = getString(R.string.service_unavailable)
|
|
tvCurrency2.visibility = View.GONE
|
|
tvFeeEquivalent.visibility = View.GONE
|
|
} else
|
|
tvFeeEquivalent.error = null
|
|
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
tvFeeEquivalent.text = ""
|
|
}
|
|
}
|
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
|
}
|
|
})
|
|
btnSend.setOnClickListener {
|
|
if (UtilHelper.isOnline(this)) {
|
|
val calendar = Calendar.getInstance()
|
|
calendar.add(Calendar.MINUTE, -1)
|
|
|
|
if (dtVerified == null || dtVerified!!.before(calendar.time)) {
|
|
finishWithError(Activity.RESULT_CANCELED, getString(R.string.the_obtained_data_is_outdated_try_again))
|
|
return@setOnClickListener
|
|
}
|
|
|
|
val engineCoin = CoinEngineFactory.create(ctx)
|
|
|
|
if (engineCoin!!.isNeedCheckNode && !nodeCheck) {
|
|
Toast.makeText(baseContext, getString(R.string.cannot_reach_current_active_blockchain_node_try_again), Toast.LENGTH_LONG).show()
|
|
return@setOnClickListener
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
requestPIN2Count = 0
|
|
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_)
|
|
} else
|
|
Toast.makeText(this, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
|
}
|
|
|
|
val coinEngine = CoinEngineFactory.create(ctx)
|
|
|
|
progressBar.visibility = View.VISIBLE
|
|
|
|
coinEngine!!.requestFee(
|
|
object : CoinEngine.BlockchainRequestsCallbacks {
|
|
override fun onComplete(success: Boolean) {
|
|
if (success) {
|
|
onProgress()
|
|
progressBar.visibility = View.INVISIBLE
|
|
dtVerified = Date()
|
|
} else {
|
|
finishWithError(Activity.RESULT_CANCELED, ctx.error)
|
|
}
|
|
}
|
|
|
|
override fun onProgress() {
|
|
doSetFee(rgFee.checkedRadioButtonId)
|
|
}
|
|
|
|
override fun allowAdvance(): Boolean {
|
|
return UtilHelper.isOnline(this@ConfirmTransactionActivity)
|
|
}
|
|
},
|
|
etWallet.text.toString(),
|
|
amount)
|
|
}
|
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
if (requestCode == Constant.REQUEST_CODE_SIGN_TRANSACTION) {
|
|
if (data != null && data.extras != null) {
|
|
if (data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) {
|
|
val updatedCard = TangemCard(data.getStringExtra("UID"))
|
|
updatedCard.loadFromBundle(data.getBundleExtra("Card"))
|
|
ctx.card = updatedCard
|
|
}
|
|
}
|
|
if (resultCode == Constant.RESULT_INVALID_PIN_ && requestPIN2Count < 2) {
|
|
requestPIN2Count++
|
|
|
|
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_)
|
|
|
|
return
|
|
}
|
|
setResult(resultCode, data)
|
|
finish()
|
|
} else if (requestCode == Constant.REQUEST_CODE_REQUEST_PIN2_) {
|
|
if (resultCode == Activity.RESULT_OK) {
|
|
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_SIGN_TRANSACTION)
|
|
} else
|
|
Toast.makeText(baseContext, R.string.pin_2_is_required_to_sign_the_transaction, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
|
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
|
when (keyCode) {
|
|
KeyEvent.KEYCODE_BACK -> {
|
|
val intent = Intent()
|
|
setResult(Activity.RESULT_CANCELED, intent)
|
|
finish()
|
|
return true
|
|
}
|
|
}
|
|
return super.onKeyDown(keyCode, event)
|
|
}
|
|
|
|
override fun onTagDiscovered(tag: Tag) {
|
|
try {
|
|
nfcManager.ignoreTag(tag)
|
|
} catch (e: IOException) {
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
|
|
private fun doSetFee(checkedRadioButtonId: Int) {
|
|
var txtFee = ""
|
|
when (checkedRadioButtonId) {
|
|
R.id.rbMinimalFee ->
|
|
if (ctx.coinData.minFee != null) {
|
|
txtFee = ctx.coinData.minFee!!.toValueString()
|
|
btnSend.visibility = View.VISIBLE
|
|
} else
|
|
btnSend.visibility = View.INVISIBLE
|
|
|
|
R.id.rbNormalFee ->
|
|
if (ctx.coinData.normalFee != null) {
|
|
txtFee = ctx.coinData.normalFee!!.toValueString()
|
|
btnSend.visibility = View.VISIBLE
|
|
} else
|
|
btnSend.visibility = View.INVISIBLE
|
|
|
|
R.id.rbMaximumFee ->
|
|
if (ctx.coinData.maxFee != null) {
|
|
txtFee = ctx.coinData.maxFee!!.toValueString()
|
|
btnSend.visibility = View.VISIBLE
|
|
} else
|
|
btnSend.visibility = View.INVISIBLE
|
|
}
|
|
etFee.setText(txtFee.replace(',', '.'))
|
|
}
|
|
|
|
private fun finishWithError(errorCode: Int, message: String) {
|
|
val transactionFinishWithError = TransactionFinishWithError()
|
|
transactionFinishWithError.message = message
|
|
EventBus.getDefault().post(transactionFinishWithError)
|
|
|
|
val intent = Intent()
|
|
intent.putExtra("message", message)
|
|
setResult(errorCode, intent)
|
|
finish()
|
|
}
|
|
|
|
} |