tangem-app-android-audited/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.kt
2018-10-07 15:32:37 +03:00

1135 lines
No EOL
49 KiB
Kotlin

package com.tangem.presentation.fragment
import android.app.Activity
import android.app.AlertDialog
import android.content.*
import android.content.Context.CLIPBOARD_SERVICE
import android.content.pm.PackageManager
import android.content.res.ColorStateList
import android.nfc.NfcAdapter
import android.nfc.Tag
import android.nfc.tech.IsoDep
import android.os.Bundle
import android.preference.PreferenceManager
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v4.widget.SwipeRefreshLayout
import android.text.Html
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.google.zxing.WriterException
import com.tangem.data.network.ServerApiHelper
import com.tangem.data.network.model.InfuraResponse
import com.tangem.data.network.request.ElectrumRequest
import com.tangem.data.nfc.VerifyCardTask
import com.tangem.domain.cardReader.CardProtocol
import com.tangem.domain.cardReader.NfcManager
import com.tangem.domain.wallet.*
import com.tangem.presentation.activity.*
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
import com.tangem.presentation.dialog.PINSwapWarningDialog
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
import com.tangem.util.BTCUtils
import com.tangem.util.Util
import com.tangem.util.UtilHelper
import com.tangem.wallet.BuildConfig
import com.tangem.wallet.R
import kotlinx.android.synthetic.main.fr_loaded_wallet.*
import org.json.JSONException
import java.math.BigInteger
import java.util.*
class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, SharedPreferences.OnSharedPreferenceChangeListener {
companion object {
val TAG: String = LoadedWallet::class.java.simpleName
private const val REQUEST_CODE_SEND_PAYMENT = 1
private const val REQUEST_CODE_VERIFY_CARD = 4
private const val REQUEST_CODE_PURGE = 2
private const val REQUEST_CODE_REQUEST_PIN2_FOR_PURGE = 3
private const val REQUEST_CODE_ENTER_NEW_PIN = 5
private const val REQUEST_CODE_ENTER_NEW_PIN2 = 6
private const val REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN = 7
private const val REQUEST_CODE_SWAP_PIN = 8
private const val REQUEST_CODE_RECEIVE_PAYMENT = 9
}
private var singleToast: Toast? = null
private var nfcManager: NfcManager? = null
private var serverApiHelper: ServerApiHelper? = null
var card: TangemCard? = null
private var lastTag: Tag? = null
var srlLoadedWallet: SwipeRefreshLayout? = null
private var lastReadSuccess = true
private var verifyCardTask: VerifyCardTask? = null
private var requestPIN2Count = 0
private var timerHideErrorAndMessage: Timer? = null
private var newPIN = ""
private var newPIN2 = ""
private var cardProtocol: CardProtocol? = null
private var sp: SharedPreferences? = null
private val inactiveColor: ColorStateList by lazy { resources.getColorStateList(R.color.btn_dark) }
private val activeColor: ColorStateList by lazy { resources.getColorStateList(R.color.colorAccent) }
private var timerRepeatRefresh: Timer? = null
private lateinit var localStorage: LocalStorage
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
nfcManager = NfcManager(activity, this)
serverApiHelper = ServerApiHelper()
sp = PreferenceManager.getDefaultSharedPreferences(activity)
card = TangemCard(activity!!.intent.getStringExtra(TangemCard.EXTRA_UID))
card!!.loadFromBundle(activity!!.intent.extras.getBundle(TangemCard.EXTRA_CARD))
lastTag = activity!!.intent.getParcelableExtra(MainActivity.EXTRA_LAST_DISCOVERED_TAG)
localStorage = LocalStorage(context!!)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val v = inflater.inflate(R.layout.fr_loaded_wallet, container, false)
srlLoadedWallet = v.findViewById(R.id.srlLoadedWallet)
return v
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (card!!.blockchain == Blockchain.Token)
tvBalance.setSingleLine(false)
//ivTangemCard.setImageResource(card!!.cardImageResource)
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!))
val engine = CoinEngineFactory.create(card!!.blockchain)
val visibleFlag = engine?.inOutPutVisible() ?: true
try {
ivQR.setImageBitmap(UtilHelper.generateQrCode(engine.getShareWalletUri(card).toString()))
} catch (e: WriterException) {
e.printStackTrace()
}
btnExtract.backgroundTintList = inactiveColor
refresh()
startVerify(lastTag)
tvWallet.text = card!!.wallet
// set listeners
srlLoadedWallet!!.setOnRefreshListener { refresh() }
btnLookup.setOnClickListener {
val engineClick = CoinEngineFactory.create(card!!.blockchain)
val browserIntent = Intent(Intent.ACTION_VIEW, engineClick.getShareWalletUriExplorer(card))
startActivity(browserIntent)
}
btnCopy.setOnClickListener { doShareWallet(false) }
tvWallet.setOnClickListener { doShareWallet(false) }
ivQR.setOnClickListener { doShareWallet(true) }
btnLoad.setOnClickListener {
if (BuildConfig.DEBUG) {
val items = arrayOf<CharSequence>(getString(R.string.in_app), getString(R.string.via_cryptonit), getString(R.string.via_kraken))
val dialog = AlertDialog.Builder(activity).setTitle(getString(R.string.select_loading_method)).setItems(items
) { _, which ->
when (items[which]) {
getString(R.string.in_app) -> {
try {
val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card))
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
} catch (e: ActivityNotFoundException) {
showSingleToast(R.string.no_compatible_wallet)
}
}
// getString(R.string.via_cryptonit2) -> {
// val intent = Intent(context, PrepareCryptonitOtherAPIWithdrawalActivity::class.java)
// intent.putExtra("UID", card!!.uid)
// intent.putExtra("Card", card!!.asBundle)
// startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
// }
getString(R.string.via_cryptonit) -> {
val intent = Intent(context, PrepareCryptonitWithdrawalActivity::class.java)
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
}
getString(R.string.via_kraken) -> {
val intent = Intent(context, PrepareKrakenWithdrawalActivity::class.java)
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
}
else -> {
}
}
}
dialog.show()
} else {
try {
val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card))
intent.addCategory(Intent.CATEGORY_DEFAULT)
startActivity(intent)
} catch (e: ActivityNotFoundException) {
showSingleToast(R.string.no_compatible_wallet)
}
}
}
btnDetails.setOnClickListener {
if (cardProtocol != null)
openVerifyCard(cardProtocol!!)
else
showSingleToast(R.string.need_attach_card_again)
}
btnScanAgain.setOnClickListener {
val intent = Intent(context, MainActivity::class.java)
startActivity(intent)
}
btnExtract.setOnClickListener {
if (!card!!.hasBalanceInfo()) {
showSingleToast(R.string.cannot_obtain_data_from_blockchain)
} else if (!engine.isBalanceNotZero(card))
showSingleToast(R.string.wallet_empty)
else if (!engine.isBalanceAlterNotZero(card))
showSingleToast(R.string.not_enough_funds_or_incorrect_amount)
else if (engine.awaitingConfirmation(card))
showSingleToast(R.string.please_wait_while_previous)
else if (!engine.checkUnspentTransaction(card))
showSingleToast(R.string.please_wait_for_confirmation)
else if (card!!.remainingSignatures == 0)
showSingleToast(R.string.card_has_no_remaining_signature)
else {
val intent = Intent(context, PreparePaymentActivity::class.java)
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT)
}
}
// request electrum listener
serverApiHelper!!.setElectrumRequestData {
if (it.isMethod(ElectrumRequest.METHOD_GetBalance)) {
try {
val walletAddress = it.params.getString(0)
val confBalance = it.result.getLong("confirmed")
val unconfirmedBalance = it.result.getLong("unconfirmed")
card!!.isBalanceReceived = true
card!!.setBalanceConfirmed(confBalance)
card!!.balanceUnconfirmed = unconfirmedBalance
card!!.decimalBalance = confBalance.toString()
card!!.validationNodeDescription = serverApiHelper!!.validationNodeDescription
} catch (e: JSONException) {
e.printStackTrace()
engine.switchNode(card)
}
}
if (it.isMethod(ElectrumRequest.METHOD_ListUnspent)) {
try {
val mWalletAddress = it.params.getString(0)
val jsUnspentArray = it.resultArray
try {
card!!.unspentTransactions.clear()
for (i in 0 until jsUnspentArray.length()) {
val jsUnspent = jsUnspentArray.getJSONObject(i)
val trUnspent = TangemCard.UnspentTransaction()
trUnspent.txID = jsUnspent.getString("tx_hash")
trUnspent.Amount = jsUnspent.getInt("value")
trUnspent.Height = jsUnspent.getInt("height")
card!!.unspentTransactions.add(trUnspent)
}
} catch (e: JSONException) {
e.printStackTrace()
engine.switchNode(card)
}
for (i in 0 until jsUnspentArray.length()) {
val jsUnspent = jsUnspentArray.getJSONObject(i)
val height = jsUnspent.getInt("height")
val hash = jsUnspent.getString("tx_hash")
if (height != -1) {
// val nodeAddress = engine.getNode(card)
// val nodePort = engine.getNodePort(card)
// val updateWalletInfoTask = UpdateWalletInfoTask(this, nodeAddress, nodePort)
// // loadedWallet.updateTasks.add(updateWalletInfoTask);
// updateWalletInfoTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.getHeader(mWalletAddress, height.toString()), ElectrumRequest.getTransaction(mWalletAddress, hash))
requestElectrum(card!!, ElectrumRequest.getHeader(mWalletAddress, height.toString()))
requestElectrum(card!!, ElectrumRequest.getTransaction(mWalletAddress, hash))
}
}
} catch (e: JSONException) {
e.printStackTrace()
engine.switchNode(card)
}
}
if (it.isMethod(ElectrumRequest.METHOD_GetHeader)) {
try {
val jsHeader = it.result
try {
card!!.haedersInfo
card!!.UpdateHeaderInfo(TangemCard.HeaderInfo(jsHeader.getInt("block_height"), jsHeader.getInt("timestamp")))
} catch (e: JSONException) {
e.printStackTrace()
}
} catch (e: JSONException) {
e.printStackTrace()
}
}
if (it.isMethod(ElectrumRequest.METHOD_GetTransaction)) {
try {
val txHash = it.txHash
val raw = it.resultString
val listTx = card!!.unspentTransactions
for (tx in listTx) {
if (tx.txID == txHash)
tx.Raw = raw
}
val listHTx = card!!.historyTransactions
for (tx in listHTx) {
if (tx.txID == txHash) {
tx.Raw = raw
try {
val prevHashes = BTCUtils.getPrevTX(raw)
var isOur = false
for (hash in prevHashes) {
val checkID = BTCUtils.toHex(hash)
for (txForCheck in listHTx) {
if (txForCheck.txID == checkID)
isOur = true
}
}
tx.isInput = !isOur
} catch (e: BitcoinException) {
e.printStackTrace()
}
}
}
} catch (e: JSONException) {
e.printStackTrace()
}
}
if (it.isMethod(ElectrumRequest.METHOD_SendTransaction)) {
try {
var hashTX = it.resultString
try {
LastSignStorage.setLastMessage(card!!.wallet, hashTX)
if (hashTX.startsWith("0x") || hashTX.startsWith("0X"))
hashTX = hashTX.substring(2)
val bigInt = BigInteger(hashTX, 16) //TODO: очень плохой способ
LastSignStorage.setTxWasSend(card!!.wallet)
LastSignStorage.setLastMessage(card!!.wallet, "")
} catch (e: Exception) {
e.printStackTrace()
}
} catch (e: JSONException) {
e.printStackTrace()
}
}
}
// request card verify listener
serverApiHelper!!.setCardVerifyAndGetInfoListener {
srlLoadedWallet!!.isRefreshing = false
updateViews()
val result = it.results!![0]
if (result.error != null) {
// Log.e(TAG, "Can't verify card: ${result.error}")
card!!.isOnlineVerified = false
return@setCardVerifyAndGetInfoListener
}
card!!.isOnlineVerified = result.passed
if (!result.passed) return@setCardVerifyAndGetInfoListener
if (localStorage.checkBatchInfoChanged(card!!, result)) {
Log.w(TAG, "Batch ${result.batch} info changed to '$result'")
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!))
localStorage.applySubstitution(card!!)
if (card!!.blockchain == Blockchain.Token || card!!.blockchain == Blockchain.Ethereum) {
//TODO: change this very bad code - it need because we have switch to token from ethereum if token symbol specified
card!!.setBlockchainIDFromCard(Blockchain.Ethereum.id)
}
updateViews()
refresh()
}
if (result.artwork != null && localStorage.checkNeedUpdateArtwork(result.artwork)) {
Log.w(TAG, "Artwork '${result.artwork!!.id}' updated, need download")
serverApiHelper!!.requestArtwork(result.artwork!!.id, result.artwork!!.getUpdateDate(), card!!)
updateViews()
}
// Log.i(TAG, "setCardVerify " + it.results!![0].passed)
}
serverApiHelper!!.setArtworkListener { artworkId, inputStream, updateDate ->
Log.w(TAG, "Artwork '$artworkId' downloaded")
localStorage.updateArtwork(artworkId, inputStream, updateDate)
ivTangemCard.setImageBitmap(localStorage.getCardArtworkBitmap(card!!))
}
// request rate info listener
serverApiHelper!!.setRateInfoData {
val rate = it.priceUsd.toFloat()
card!!.rate = rate
card!!.rateAlter = rate
srlLoadedWallet!!.isRefreshing = false
updateViews()
// Log.i(TAG, "setRateInfoData $rate")
}
// request eth get balance, eth get transaction count, eth call, eth sendRawTransaction listener
val infuraBodyListener: ServerApiHelper.InfuraBodyListener = object : ServerApiHelper.InfuraBodyListener {
override fun onInfuraSuccess(method: String, infuraResponse: InfuraResponse) {
when (method) {
ServerApiHelper.INFURA_ETH_GET_BALANCE -> {
var balanceCap = infuraResponse.result
balanceCap = balanceCap.substring(2)
val l = BigInteger(balanceCap, 16)
val d = l.divide(BigInteger("1000000000000000000", 10))
val balance = d.toLong()
card!!.setBalanceConfirmed(balance)
card!!.balanceUnconfirmed = 0L
card!!.isBalanceReceived = true
if (card!!.blockchain != Blockchain.Token)
card!!.decimalBalance = l.toString(10)
card!!.decimalBalanceAlter = l.toString(10)
Log.i("$TAG eth_get_balance", balanceCap)
}
ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT -> {
var nonce = infuraResponse.result
nonce = nonce.substring(2)
val count = BigInteger(nonce, 16)
card!!.confirmedTXCount = count
// Log.i("$TAG eth_getTransCount", nonce)
}
ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT -> {
var pending = infuraResponse.result
pending = pending.substring(2)
val count = BigInteger(pending, 16)
card!!.unconfirmedTXCount = count
// Log.i("$TAG eth_getPendingTxCount", pending)
}
ServerApiHelper.INFURA_ETH_CALL -> {
try {
var balanceCap = infuraResponse.result
balanceCap = balanceCap.substring(2)
val l = BigInteger(balanceCap, 16)
val balance = l.toLong()
if (l.compareTo(BigInteger.ZERO) == 0) {
card!!.blockchainID = Blockchain.Ethereum.id
card!!.addTokenToBlockchainName()
srlLoadedWallet!!.isRefreshing = false
updateViews()
requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
return
}
card!!.setBalanceConfirmed(balance)
card!!.balanceUnconfirmed = 0L
card!!.decimalBalance = l.toString(10)
// Log.i("$TAG eth_call", balanceCap)
requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
} catch (e: JSONException) {
e.printStackTrace()
} catch (e: NumberFormatException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
}
ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION -> {
try {
var hashTX: String
try {
val tmp = infuraResponse.result
hashTX = tmp
} catch (e: JSONException) {
// val msg = request.getAnswer()
// val err = msg!!.getJSONObject("error")
// hashTX = err.getString("message")
// LastSignStorage.setLastMessage(card!!.wallet, hashTX)
return
}
if (hashTX.startsWith("0x") || hashTX.startsWith("0X")) {
hashTX = hashTX.substring(2)
}
val bigInt = BigInteger(hashTX, 16) //TODO: очень плохой способ
LastSignStorage.setTxWasSend(card!!.wallet)
LastSignStorage.setLastMessage(card!!.wallet, "")
Log.e("$TAG TX_RESULT", hashTX)
val nonce = card!!.confirmedTXCount
nonce.add(BigInteger.valueOf(1))
card!!.confirmedTXCount = nonce
Log.e("$TAG TX_RESULT", hashTX)
} catch (e: Exception) {
e.printStackTrace()
}
}
else -> {
}
}
updateViews()
}
override fun onInfuraFail(method: String, message: String) {
srlLoadedWallet!!.isRefreshing = false
updateViews()
}
}
serverApiHelper!!.setInfuraResponse(infuraBodyListener)
}
private fun requestElectrum(card: TangemCard, electrumRequest: ElectrumRequest) {
serverApiHelper!!.electrumRequestData(card, electrumRequest)
}
private fun requestInfura(method: String, contract: String) {
serverApiHelper!!.infura(method, 67, card!!.wallet, contract, LastSignStorage.getTxForSend(card!!.wallet))
}
private fun requestCardVerify() {
if ((card!!.isOnlineVerified == null || !card!!.isOnlineVerified))
serverApiHelper!!.cardVerifyAndGetInfo(card) //serverApiHelper!!.cardVerify(card)
}
private fun requestRateInfo(cryptoId: String) {
serverApiHelper!!.rateInfoData(cryptoId)
}
override fun onResume() {
super.onResume()
nfcManager!!.onResume()
}
override fun onPause() {
super.onPause()
nfcManager!!.onPause()
if (timerRepeatRefresh != null)
timerRepeatRefresh!!.cancel()
}
override fun onStop() {
super.onStop()
nfcManager!!.onStop()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
var data = data
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQUEST_CODE_VERIFY_CARD ->
// action when erase wallet
if (resultCode == Activity.RESULT_OK) {
if (activity != null)
activity!!.finish()
}
REQUEST_CODE_ENTER_NEW_PIN -> if (resultCode == Activity.RESULT_OK) {
if (data != null) {
if (data.extras != null && data.extras!!.containsKey("confirmPIN")) {
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
newPIN = data.getStringExtra("newPIN")
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
} else {
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("newPIN", data.getStringExtra("newPIN"))
intent.putExtra("mode", PinRequestActivity.Mode.ConfirmNewPIN.toString())
startActivityForResult(intent, REQUEST_CODE_ENTER_NEW_PIN)
}
}
}
REQUEST_CODE_ENTER_NEW_PIN2 -> if (resultCode == Activity.RESULT_OK) {
if (data != null) {
if (data.extras != null && data.extras!!.containsKey("confirmPIN2")) {
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
newPIN2 = data.getStringExtra("newPIN2")
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
} else {
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("newPIN2", data.getStringExtra("newPIN2"))
intent.putExtra("mode", PinRequestActivity.Mode.ConfirmNewPIN2.toString())
startActivityForResult(intent, REQUEST_CODE_ENTER_NEW_PIN2)
}
}
}
REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) {
if (newPIN == "")
newPIN = card!!.pin
if (newPIN2 == "")
newPIN2 = PINStorage.getPIN2()
val pinSwapWarningDialog = PINSwapWarningDialog()
pinSwapWarningDialog.setOnRefreshPage { startSwapPINActivity() }
val bundle = Bundle()
if (!PINStorage.isDefaultPIN(newPIN) || !PINStorage.isDefaultPIN2(newPIN2))
bundle.putString(PINSwapWarningDialog.EXTRA_MESSAGE, getString(R.string.if_you_forget))
else
bundle.putString(PINSwapWarningDialog.EXTRA_MESSAGE, getString(R.string.if_you_use_default))
pinSwapWarningDialog.arguments = bundle
pinSwapWarningDialog.show(activity!!.fragmentManager, PINSwapWarningDialog.TAG)
}
REQUEST_CODE_SWAP_PIN -> if (resultCode == Activity.RESULT_OK) {
if (data == null) {
data = Intent()
data.putExtra("UID", card!!.uid)
data.putExtra("Card", card!!.asBundle)
data.putExtra("modification", "delete")
} else
data.putExtra("modification", "update")
if (activity != null) {
activity!!.setResult(Activity.RESULT_OK, data)
activity!!.finish()
}
} else {
if (data != null && data.extras != null && data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) {
val updatedCard = TangemCard(data.getStringExtra("UID"))
updatedCard.loadFromBundle(data.getBundleExtra("Card"))
card = updatedCard
}
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
requestPIN2Count++
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN)
return
} else {
if (data != null && data.extras!!.containsKey("message")) {
card!!.error = data.getStringExtra("message")
}
}
}
REQUEST_CODE_REQUEST_PIN2_FOR_PURGE -> if (resultCode == Activity.RESULT_OK) {
val intent = Intent(context, PurgeActivity::class.java)
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_PURGE)
}
REQUEST_CODE_PURGE -> if (resultCode == Activity.RESULT_OK) {
if (data == null) {
data = Intent()
data.putExtra("UID", card!!.uid)
data.putExtra("Card", card!!.asBundle)
data.putExtra("modification", "delete")
} else {
data.putExtra("modification", "update")
}
if (activity != null) {
activity!!.setResult(Activity.RESULT_OK, data)
activity!!.finish()
}
} else {
if (data != null && data.extras != null && data.extras!!.containsKey("UID") && data.extras!!.containsKey("Card")) {
val updatedCard = TangemCard(data.getStringExtra("UID"))
updatedCard.loadFromBundle(data.getBundleExtra("Card"))
card = updatedCard
}
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
requestPIN2Count++
val intent = Intent(context, PinRequestActivity::class.java)
intent.putExtra("mode", PinRequestActivity.Mode.RequestPIN2.toString())
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_PURGE)
return
} else {
if (data != null && data.extras!!.containsKey("message")) {
card!!.error = data.getStringExtra("message")
}
}
updateViews()
}
REQUEST_CODE_SEND_PAYMENT, REQUEST_CODE_RECEIVE_PAYMENT -> {
// if (resultCode == Activity.RESULT_OK) {
//// srlLoadedWallet!!.postDelayed({ refresh() }, 10000)
//// srlLoadedWallet!!.isRefreshing = true
//
// timerRepeatRefresh = fixedRateTimer(name = "refresh", initialDelay = 2000, period = 5000) {
// activity!!.runOnUiThread {
// refresh()
// Log.i("sfsf", "refresh")
// }
// }
// card!!.clearInfo()
//
//// updateViews()
// }
if (resultCode == Activity.RESULT_OK) {
srlLoadedWallet!!.postDelayed({ this.refresh() }, 5000)
srlLoadedWallet!!.isRefreshing = true
card!!.clearInfo()
updateViews()
}
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"))
card = updatedCard
}
if (data.extras!!.containsKey("message")) {
if (resultCode == Activity.RESULT_OK) {
card!!.message = data.getStringExtra("message")
} else {
card!!.error = data.getStringExtra("message")
}
}
updateViews()
}
}
}
}
override fun onTagDiscovered(tag: Tag) {
startVerify(tag)
}
override fun onReadStart(cardProtocol: CardProtocol) {
rlProgressBar.post { rlProgressBar.visibility = View.VISIBLE }
}
override fun onReadProgress(protocol: CardProtocol, progress: Int) {
}
override fun onReadFinish(cardProtocol: CardProtocol?) {
verifyCardTask = null
if (cardProtocol != null) {
if (cardProtocol.error == null) {
rlProgressBar.post {
rlProgressBar.visibility = View.GONE
this.cardProtocol = cardProtocol
if (!cardProtocol.card.isWalletPublicKeyValid) refresh()
else updateViews()
}
} else {
// remove last UIDs because of error and no card read
rlProgressBar.post {
lastReadSuccess = false
if (cardProtocol.error is CardProtocol.TangemException_ExtendedLengthNotSupported)
if (!NoExtendedLengthSupportDialog.allReadyShowed)
NoExtendedLengthSupportDialog().show(activity!!.fragmentManager, NoExtendedLengthSupportDialog.TAG)
else
Toast.makeText(context, R.string.try_to_scan_again, Toast.LENGTH_SHORT).show()
}
}
}
rlProgressBar.postDelayed({
try {
rlProgressBar.visibility = View.GONE
} catch (e: Exception) {
e.printStackTrace()
}
}, 500)
}
override fun onReadCancel() {
verifyCardTask = null
rlProgressBar.postDelayed({
try {
rlProgressBar.visibility = View.GONE
} catch (e: Exception) {
e.printStackTrace()
}
}, 500)
}
override fun onReadWait(msec: Int) {
WaitSecurityDelayDialog.OnReadWait(activity!!, msec)
}
override fun onReadBeforeRequest(timeout: Int) {
WaitSecurityDelayDialog.onReadBeforeRequest(activity!!, timeout)
}
override fun onReadAfterRequest() {
WaitSecurityDelayDialog.onReadAfterRequest(activity!!)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
}
fun updateViews() {
try {
if (timerHideErrorAndMessage != null) {
timerHideErrorAndMessage!!.cancel()
timerHideErrorAndMessage = null
}
if (card!!.error == null || card!!.error.isEmpty()) {
tvError.visibility = View.GONE
tvError.text = ""
} else {
tvError.visibility = View.VISIBLE
tvError.text = card!!.error
}
val needResendTX = LastSignStorage.getNeedTxSend(card!!.wallet)
if ((card!!.message == null || card!!.message.isEmpty()) && !needResendTX) {
tvMessage!!.text = ""
tvMessage!!.visibility = View.GONE
} else {
if (needResendTX) {
} else {
tvMessage!!.text = card!!.message
}
tvMessage!!.visibility = View.VISIBLE
}
val engine = CoinEngineFactory.create(card!!.blockchain)
if (srlLoadedWallet!!.isRefreshing) {
tvBalanceLine1.setTextColor(resources.getColor(R.color.primary))
tvBalanceLine1.text = "Verifying in blockchain..."
tvBalanceLine2.text = ""
} else {
val validator = BalanceValidator()
validator.Check(card, false)
tvBalanceLine1.setTextColor(ContextCompat.getColor(context!!, validator.color))
tvBalanceLine1.text = validator.firstLine
tvBalanceLine2.text = validator.getSecondLine(false)
}
if (engine!!.hasBalanceInfo(card) || card!!.offlineBalance == null) {
if (card!!.blockchain == Blockchain.Token) {
val html = Html.fromHtml(engine.getBalanceWithAlter(card))
tvBalance.text = html
} else
tvBalance.text = engine.getBalanceWithAlter(card)
} else {
val offlineAmount = engine.convertByteArrayToAmount(card, card!!.offlineBalance)
if (card!!.blockchain == Blockchain.Token) {
tvBalance.setText(R.string.not_implemented)
} else
tvBalance.text = engine.getAmountDescription(card, offlineAmount)
}
tvWallet.text = card!!.wallet
tvBlockchain.text = card!!.blockchainName
if (card!!.hasBalanceInfo() && (card!!.balance != 0L)) {
btnExtract.isEnabled = true
btnExtract.backgroundTintList = activeColor
} else {
btnExtract.isEnabled = false
btnExtract.backgroundTintList = inactiveColor
}
card!!.error = null
card!!.message = null
} catch (e: Exception) {
e.printStackTrace()
}
}
fun refresh() {
srlLoadedWallet!!.isRefreshing = true
card!!.clearInfo()
card!!.error = null
card!!.message = null
card!!.isBalanceReceived = false
val needResendTX = LastSignStorage.getNeedTxSend(card!!.wallet)
updateViews()
val engine = CoinEngineFactory.create(card!!.blockchain)
requestCardVerify()
// Bitcoin
if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet) {
// val data = SharedData(SharedData.COUNT_REQUEST)
card!!.resetFailedBalanceRequestCounter()
card!!.setIsBalanceEqual(true)
requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet))
requestElectrum(card!!, ElectrumRequest.listUnspent(card!!.wallet))
// for (i in 0 until data.allRequest) {
// val nodeAddress = engine!!.getNextNode(card)
// val nodePort = engine.getNextNodePort(card)
//
//// Log.i(TAG, nodeAddress)
//// Log.i(TAG, nodePort.toString())
//// Log.i(TAG, i.toString())
//
// // check balance
// val connectTaskEx = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort, data)
// connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.checkBalance(card!!.wallet))
//
// // list unspent input
// val updateWalletInfoTask = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort, data)
// updateWalletInfoTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.listUnspent(card!!.wallet))
// }
requestRateInfo("bitcoin")
}
// BitcoinCash
else if (card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) {
// val data = SharedData(SharedData.COUNT_REQUEST)
card!!.resetFailedBalanceRequestCounter()
card!!.setIsBalanceEqual(true)
requestElectrum(card!!, ElectrumRequest.checkBalance(card!!.wallet))
requestElectrum(card!!, ElectrumRequest.listUnspent(card!!.wallet))
// for (i in 0 until data.allRequest) {
// val nodeAddress = engine!!.getNextNode(card)
// val nodePort = engine.getNextNodePort(card)
//
// // check balance
// val connectTaskEx = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort, data)
// connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.checkBalance(card!!.wallet))
// }
//
// val nodeAddress = engine!!.getNode(card)
// val nodePort = engine.getNodePort(card)
//
// // list unspent input
// val updateWalletInfoTask = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort, data)
// updateWalletInfoTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.listUnspent(card!!.wallet))
requestRateInfo("bitcoin-cash")
}
// Ethereum
else if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet) {
// val updateETH = ETHRequestTask(this@LoadedWallet, card!!.blockchain)
//
// val reqETH = InfuraRequest.GetBalance(card!!.wallet)
// reqETH.id = 67
// reqETH.setBlockchain(card!!.blockchain)
//
// val reqNonce = InfuraRequest.GetOutTransactionCount(card!!.wallet)
// reqNonce.id = 67
// reqNonce.setBlockchain(card!!.blockchain)
//
// updateETH.execute(reqETH, reqNonce)
requestInfura(ServerApiHelper.INFURA_ETH_GET_BALANCE, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_TRANSACTION_COUNT, "")
requestInfura(ServerApiHelper.INFURA_ETH_GET_PENDING_COUNT, "")
requestRateInfo("ethereum")
}
// Token
else if (card!!.blockchain == Blockchain.Token) {
// val updateETH = ETHRequestTask(this@LoadedWallet, card!!.blockchain)
//
// val reqETH = InfuraRequest.GetTokenBalance(card!!.wallet, engine!!.getContractAddress(card), engine.getTokenDecimals(card))
// reqETH.id = 67
// reqETH.setBlockchain(card!!.blockchain)
//
// val reqBalance = InfuraRequest.GetBalance(card!!.wallet)
// reqBalance.id = 67
// reqBalance.setBlockchain(card!!.blockchain)
//
// val reqNonce = InfuraRequest.GetOutTransactionCount(card!!.wallet)
// reqNonce.id = 67
// reqNonce.setBlockchain(card!!.blockchain)
//
// updateETH.execute(reqETH, reqNonce, reqBalance)
requestInfura(ServerApiHelper.INFURA_ETH_CALL, engine.getContractAddress(card))
requestRateInfo("ethereum")
}
//if (needResendTX)
//sendTransaction(LastSignStorage.getTxForSend(card!!.wallet))
// if (btnExtract.isEnabled)
}
fun prepareResultIntent(): Intent {
val data = Intent()
data.putExtra("UID", card!!.uid)
data.putExtra("Card", card!!.asBundle)
return data
}
private fun openVerifyCard(cardProtocol: CardProtocol) {
val intent = Intent(context, VerifyCardActivity::class.java)
intent.putExtra("UID", cardProtocol.card.uid)
intent.putExtra("Card", cardProtocol.card.asBundle)
startActivityForResult(intent, REQUEST_CODE_VERIFY_CARD)
}
private fun startVerify(tag: Tag?) {
try {
val isoDep = IsoDep.get(tag)
?: throw CardProtocol.TangemException(getString(R.string.wrong_tag_err))
val uid = tag!!.id
val sUID = Util.byteArrayToHexString(uid)
if (card!!.uid != sUID) {
// Log.d(TAG, "Invalid UID: $sUID")
nfcManager!!.ignoreTag(isoDep.tag)
return
} else {
// Log.v(TAG, "UID: $sUID")
}
if (lastReadSuccess) {
isoDep.timeout = 1000
} else {
isoDep.timeout = 65000
}
verifyCardTask = VerifyCardTask(context, card, nfcManager, isoDep, this)
verifyCardTask!!.start()
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun doShareWallet(useURI: Boolean) {
if (useURI) {
val txtShare = CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card).toString()
val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_SUBJECT, "Wallet address")
intent.putExtra(Intent.EXTRA_TEXT, txtShare)
val packageManager = activity!!.packageManager
val activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL)
val isIntentSafe = activities.size > 0
if (isIntentSafe) {
// create intent to show chooser
val chooser = Intent.createChooser(intent, getString(R.string.share_wallet_address_with))
// verify the intent will resolve to at least one activity
if (intent.resolveActivity(activity!!.packageManager) != null) {
startActivity(chooser)
}
} else {
val clipboard = activity!!.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText(txtShare, txtShare)
Toast.makeText(context, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
}
} else {
val txtShare = card!!.wallet
val clipboard = activity!!.getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
clipboard.primaryClip = ClipData.newPlainText(txtShare, txtShare)
Toast.makeText(context, R.string.copied_clipboard, Toast.LENGTH_LONG).show()
}
}
private fun sendTransaction(tx: String) {
val engine = CoinEngineFactory.create(card!!.blockchain)
if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet || card!!.blockchain == Blockchain.Token) {
// val task = ETHRequestTask(this@LoadedWallet, card!!.blockchain)
// val req = InfuraRequest.SendTransaction(card!!.wallet, tx)
// req.id = 67
// req.setBlockchain(card!!.blockchain)
// task.execute(req)
requestInfura(ServerApiHelper.INFURA_ETH_SEND_RAW_TRANSACTION, "")
} else if (card!!.blockchain == Blockchain.Bitcoin || card!!.blockchain == Blockchain.BitcoinTestNet) {
// val nodeAddress = engine!!.getNode(card)
// val nodePort = engine.getNodePort(card)
//
// val connectTask = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort)
// connectTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.broadcast(card!!.wallet, tx))
requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx))
} else if (card!!.blockchain == Blockchain.BitcoinCash || card!!.blockchain == Blockchain.BitcoinCashTestNet) {
// val nodeAddress = engine!!.getNode(card)
// val nodePort = engine.getNodePort(card)
//
// val connectTask = UpdateWalletInfoTask(this@LoadedWallet, nodeAddress, nodePort)
// connectTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.broadcast(card!!.wallet, tx))
requestElectrum(card!!, ElectrumRequest.broadcast(card!!.wallet, tx))
}
}
private fun startSwapPINActivity() {
val intent = Intent(context, PinSwapActivity::class.java)
intent.putExtra("UID", card!!.uid)
intent.putExtra("Card", card!!.asBundle)
intent.putExtra("newPIN", newPIN)
intent.putExtra("newPIN2", newPIN2)
startActivityForResult(intent, REQUEST_CODE_SWAP_PIN)
}
var showTime: Date = Date()
private fun showSingleToast(text: Int) {
if (singleToast == null || !singleToast!!.view.isShown || showTime.time + 2000 < Date().time) {
if (singleToast != null)
singleToast!!.cancel()
singleToast = Toast.makeText(context, text, Toast.LENGTH_LONG)
singleToast!!.show()
showTime = Date()
}
}
}