tangem-app-android-audited/app/src/main/java/com/tangem/presentation/fragment/LoadedWallet.java
2018-07-12 18:02:27 +03:00

922 lines
No EOL
42 KiB
Java

package com.tangem.presentation.fragment;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.AppCompatButton;
import android.text.Html;
import android.text.Spanned;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.WriterException;
import com.tangem.data.network.request.ElectrumRequest;
import com.tangem.data.network.request.ExchangeRequest;
import com.tangem.data.network.request.InfuraRequest;
import com.tangem.data.network.task.loaded_wallet.ETHRequestTask;
import com.tangem.data.network.task.loaded_wallet.RateInfoTask;
import com.tangem.data.network.task.loaded_wallet.UpdateWalletInfoTask;
import com.tangem.data.nfc.VerifyCardTask;
import com.tangem.domain.cardReader.CardProtocol;
import com.tangem.domain.cardReader.NfcManager;
import com.tangem.domain.wallet.Blockchain;
import com.tangem.domain.wallet.CoinEngine;
import com.tangem.domain.wallet.CoinEngineFactory;
import com.tangem.domain.wallet.LastSignStorage;
import com.tangem.domain.wallet.PINStorage;
import com.tangem.domain.wallet.SharedData;
import com.tangem.domain.wallet.TangemCard;
import com.tangem.presentation.activity.CreateNewWalletActivity;
import com.tangem.presentation.activity.MainActivity;
import com.tangem.presentation.activity.PreparePaymentActivity;
import com.tangem.presentation.activity.PurgeActivity;
import com.tangem.presentation.activity.RequestPINActivity;
import com.tangem.presentation.activity.SwapPINActivity;
import com.tangem.presentation.activity.VerifyCardActivity;
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog;
import com.tangem.presentation.dialog.PINSwapWarningDialog;
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
import com.tangem.util.Util;
import com.tangem.util.UtilHelper;
import com.tangem.wallet.R;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import static android.content.Context.CLIPBOARD_SERVICE;
public class LoadedWallet extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback, CardProtocol.Notifications {
public static final String TAG = LoadedWallet.class.getSimpleName();
private static final int REQUEST_CODE_SEND_PAYMENT = 1;
private static final int REQUEST_CODE_VERIFY_CARD = 4;
private static final int REQUEST_CODE_PURGE = 2;
private static final int REQUEST_CODE_REQUEST_PIN2_FOR_PURGE = 3;
private static final int REQUEST_CODE_ENTER_NEW_PIN = 5;
private static final int REQUEST_CODE_ENTER_NEW_PIN2 = 6;
private static final int REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN = 7;
private static final int REQUEST_CODE_SWAP_PIN = 8;
private NfcManager mNfcManager;
public TangemCard mCard;
private Tag lastTag;
public SwipeRefreshLayout mSwipeRefreshLayout;
private RelativeLayout rlProgressBar;
private TextView tvCardID, tvBalance, tvOffline, tvBalanceEquivalent, tvWallet, tvInputs, tvError, tvMessage, tvIssuer, tvBlockchain, tvValidationNode, tvHeader, tvCaution;
private ProgressBar progressBar;
private ImageView ivBlockchain, ivPIN, ivPIN2orSecurityDelay, ivDeveloperVersion;
private AppCompatButton btnExtract;
public List<UpdateWalletInfoTask> updateTasks = new ArrayList<>();
private boolean lastReadSuccess = true;
private VerifyCardTask verifyCardTask = null;
private int requestPIN2Count = 0;
private Timer timerHideErrorAndMessage = null;
private String newPIN = "", newPIN2 = "";
private CardProtocol mCardProtocol;
private int scanTimes = 0;
public LoadedWallet() {
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNfcManager = new NfcManager(getActivity(), this);
mCard = new TangemCard(Objects.requireNonNull(getActivity()).getIntent().getStringExtra(TangemCard.EXTRA_CARD));
mCard.LoadFromBundle(Objects.requireNonNull(getActivity().getIntent().getExtras()).getBundle(TangemCard.EXTRA_CARD));
lastTag = getActivity().getIntent().getParcelableExtra(Main.EXTRA_LAST_DISCOVERED_TAG);
}
@Override
public View onCreateView(@NonNull final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fr_loaded_wallet, container, false);
mSwipeRefreshLayout = v.findViewById(R.id.swipe_container);
progressBar = v.findViewById(R.id.progressBar);
rlProgressBar = v.findViewById(R.id.rlProgressBar);
ImageView ivTangemCard = v.findViewById(R.id.ivTangemCard);
tvBalance = v.findViewById(R.id.tvBalance);
tvOffline = v.findViewById(R.id.tvOffline);
tvCardID = v.findViewById(R.id.tvCardID);
tvWallet = v.findViewById(R.id.tvWallet);
tvInputs = v.findViewById(R.id.tvInputs);
tvError = v.findViewById(R.id.tvError);
tvMessage = v.findViewById(R.id.tvMessage);
tvIssuer = v.findViewById(R.id.tvIssuer);
tvHeader = v.findViewById(R.id.tvHeader);
tvCaution = v.findViewById(R.id.tvCaution);
ImageView imgLookup = v.findViewById(R.id.imgLookup);
ImageView ivCopy = v.findViewById(R.id.ivCopy);
tvValidationNode = v.findViewById(R.id.tvValidationNode);
tvBlockchain = v.findViewById(R.id.tvBlockchain);
ivBlockchain = v.findViewById(R.id.imgBlockchain);
ivPIN = v.findViewById(R.id.imgPIN);
ivPIN2orSecurityDelay = v.findViewById(R.id.imgPIN2orSecurityDelay);
ivDeveloperVersion = v.findViewById(R.id.imgDeveloperVersion);
ImageView ivQR = v.findViewById(R.id.qrWallet);
FloatingActionButton fabInfo = v.findViewById(R.id.fabInfo);
FloatingActionButton fabNFC = v.findViewById(R.id.fabNFC);
AppCompatButton btnLoad = v.findViewById(R.id.btnLoad);
btnExtract = v.findViewById(R.id.btnExtract);
tvBalanceEquivalent = v.findViewById(R.id.tvBalanceEquivalent);
mSwipeRefreshLayout.setOnRefreshListener(this);
if (mCard.getBlockchain() == Blockchain.Token)
tvBalance.setSingleLine(false);
ivTangemCard.setImageResource(mCard.getCardImageResource());
final CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
boolean visibleFlag = engine != null ? engine.InOutPutVisible() : true;
int visibleIOPuts = visibleFlag ? View.VISIBLE : View.GONE;
tvInputs.setVisibility(visibleIOPuts);
try {
ivQR.setImageBitmap(UtilHelper.INSTANCE.generateQrCode(Objects.requireNonNull(engine).getShareWalletURI(mCard).toString()));
} catch (WriterException e) {
e.printStackTrace();
}
updateViews();
if (!mCard.hasBalanceInfo()) {
mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.postDelayed(this::onRefresh, 1000);
}
startVerify(lastTag);
tvWallet.setText(mCard.getWallet());
// set listeners
imgLookup.setOnClickListener(v15 -> {
if (!mCard.hasBalanceInfo()) return;
CoinEngine engineClick = CoinEngineFactory.Create(mCard.getBlockchain());
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Objects.requireNonNull(engineClick).getShareWalletURIExplorer(mCard));
startActivity(browserIntent);
});
ivCopy.setOnClickListener(v14 -> doShareWallet(false));
tvWallet.setOnClickListener(v12 -> doShareWallet(false));
ivQR.setOnClickListener(v1 -> doShareWallet(true));
btnLoad.setOnClickListener(v1 -> {
try {
Intent intent = new Intent(Intent.ACTION_VIEW, Objects.requireNonNull(CoinEngineFactory.Create(mCard.getBlockchain())).getShareWalletURI(mCard));
intent.addCategory(Intent.CATEGORY_DEFAULT);
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
}
);
fabInfo.setOnClickListener(v16 -> {
if (mCardProtocol != null)
openVerifyCard(mCardProtocol);
else {
scanTimes++;
Toast.makeText(getContext(), R.string.need_attach_card_again, Toast.LENGTH_LONG).show();
}
});
fabNFC.setOnClickListener(view -> {
Intent intent = new Intent(getContext(), MainActivity.class);
startActivity(intent);
});
btnExtract.setOnClickListener(v13 -> {
if (!mCard.hasBalanceInfo()) {
return;
} else if (!Objects.requireNonNull(engine).IsBalanceNotZero(mCard)) {
Toast.makeText(getContext(), R.string.wallet_empty, Toast.LENGTH_LONG).show();
return;
} else if (!engine.IsBalanceAlterNotZero(mCard)) {
Toast.makeText(getContext(), R.string.not_enough_funds, Toast.LENGTH_LONG).show();
return;
} else if (engine.AwaitingConfirmation(mCard)) {
Toast.makeText(getContext(), R.string.please_wait_while_previous, Toast.LENGTH_LONG).show();
return;
} else if (!engine.CheckUnspentTransaction(mCard)) {
Toast.makeText(getContext(), R.string.please_wait_for_confirmation, Toast.LENGTH_LONG).show();
return;
} else if (mCard.getRemainingSignatures() == 0) {
Toast.makeText(getContext(), R.string.card_hasn_t_remaining_signature, Toast.LENGTH_LONG).show();
return;
}
Intent intent = new Intent(getContext(), PreparePaymentActivity.class);
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT);
});
return v;
}
@Override
public void onResume() {
super.onResume();
mNfcManager.onResume();
}
@Override
public void onPause() {
super.onPause();
mNfcManager.onPause();
}
@Override
public void onStop() {
super.onStop();
for (UpdateWalletInfoTask ut : updateTasks) {
ut.cancel(true);
}
mNfcManager.onStop();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_CODE_VERIFY_CARD:
// action when erase wallet
if (resultCode == Activity.RESULT_OK) {
if (getActivity() != null)
getActivity().finish();
}
break;
case REQUEST_CODE_ENTER_NEW_PIN:
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
if (data.getExtras() != null && data.getExtras().containsKey("confirmPIN")) {
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
newPIN = data.getStringExtra("newPIN");
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN);
} else {
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("newPIN", data.getStringExtra("newPIN"));
intent.putExtra("mode", RequestPINActivity.Mode.ConfirmNewPIN.toString());
startActivityForResult(intent, REQUEST_CODE_ENTER_NEW_PIN);
}
}
}
break;
case REQUEST_CODE_ENTER_NEW_PIN2:
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
if (data.getExtras() != null && data.getExtras().containsKey("confirmPIN2")) {
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
newPIN2 = data.getStringExtra("newPIN2");
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN);
} else {
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("newPIN2", data.getStringExtra("newPIN2"));
intent.putExtra("mode", RequestPINActivity.Mode.ConfirmNewPIN2.toString());
startActivityForResult(intent, REQUEST_CODE_ENTER_NEW_PIN2);
}
}
}
break;
case REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN:
if (resultCode == Activity.RESULT_OK) {
if (newPIN.equals(""))
newPIN = mCard.getPIN();
if (newPIN2.equals(""))
newPIN2 = PINStorage.getPIN2();
PINSwapWarningDialog pinSwapWarningDialog = new PINSwapWarningDialog();
pinSwapWarningDialog.setOnRefreshPage(this::startSwapPINActivity);
Bundle bundle = new 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.setArguments(bundle);
pinSwapWarningDialog.show(Objects.requireNonNull(getActivity()).getFragmentManager(), PINSwapWarningDialog.TAG);
}
break;
case REQUEST_CODE_SWAP_PIN:
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
data = new Intent();
data.putExtra("UID", mCard.getUID());
data.putExtra("Card", mCard.getAsBundle());
data.putExtra("modification", "delete");
} else
data.putExtra("modification", "update");
if (getActivity() != null) {
getActivity().setResult(Activity.RESULT_OK, data);
getActivity().finish();
}
} else {
if (data != null && data.getExtras() != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) {
TangemCard updatedCard = new TangemCard(data.getStringExtra("UID"));
updatedCard.LoadFromBundle(data.getBundleExtra("Card"));
mCard = updatedCard;
}
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
requestPIN2Count++;
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN);
return;
} else {
if (data != null && data.getExtras().containsKey("message")) {
mCard.setError(data.getStringExtra("message"));
}
}
}
break;
case REQUEST_CODE_REQUEST_PIN2_FOR_PURGE:
if (resultCode == Activity.RESULT_OK) {
Intent intent = new Intent(getContext(), PurgeActivity.class);
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
startActivityForResult(intent, REQUEST_CODE_PURGE);
}
break;
case REQUEST_CODE_PURGE:
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
data = new Intent();
data.putExtra("UID", mCard.getUID());
data.putExtra("Card", mCard.getAsBundle());
data.putExtra("modification", "delete");
} else {
data.putExtra("modification", "update");
}
if (getActivity() != null) {
getActivity().setResult(Activity.RESULT_OK, data);
getActivity().finish();
}
} else {
if (data != null && data.getExtras() != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) {
TangemCard updatedCard = new TangemCard(data.getStringExtra("UID"));
updatedCard.LoadFromBundle(data.getBundleExtra("Card"));
mCard = updatedCard;
}
if (resultCode == CreateNewWalletActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) {
requestPIN2Count++;
Intent intent = new Intent(getContext(), RequestPINActivity.class);
intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString());
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2_FOR_PURGE);
return;
} else {
if (data != null && data.getExtras().containsKey("message")) {
mCard.setError(data.getStringExtra("message"));
}
}
updateViews();
}
break;
case REQUEST_CODE_SEND_PAYMENT:
if (resultCode == Activity.RESULT_OK) {
mSwipeRefreshLayout.postDelayed(this::onRefresh, 10000);
mSwipeRefreshLayout.setRefreshing(true);
mCard.clearInfo();
updateViews();
}
if (data != null && data.getExtras() != null) {
if (data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) {
TangemCard updatedCard = new TangemCard(data.getStringExtra("UID"));
updatedCard.LoadFromBundle(data.getBundleExtra("Card"));
mCard = updatedCard;
}
if (data.getExtras().containsKey("message")) {
if (resultCode == Activity.RESULT_OK) {
mCard.setMessage(data.getStringExtra("message"));
} else {
mCard.setError(data.getStringExtra("message"));
}
}
updateViews();
}
break;
}
}
@Override
public void onRefresh() {
// update, showing refresh animation before making http call
if (updateTasks.size() > 0) return;
mSwipeRefreshLayout.setRefreshing(true);
mCard.clearInfo();
mCard.setError(null);
mCard.setMessage(null);
boolean needResendTX = LastSignStorage.getNeedTxSend(mCard.getWallet());
updateViews();
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
if (mCard.getBlockchain() == Blockchain.Bitcoin || mCard.getBlockchain() == Blockchain.BitcoinTestNet) {
SharedData data = new SharedData(SharedData.COUNT_REQUEST);
for (int i = 0; i < data.allRequest; ++i) {
String nodeAddress = Objects.requireNonNull(engine).GetNextNode(mCard);
int nodePort = engine.GetNextNodePort(mCard);
UpdateWalletInfoTask connectTaskEx = new UpdateWalletInfoTask(LoadedWallet.this, nodeAddress, nodePort, data);
connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet()));
UpdateWalletInfoTask updateWalletInfoTask = new UpdateWalletInfoTask(LoadedWallet.this, nodeAddress, nodePort, data);
updateTasks.add(updateWalletInfoTask);
updateWalletInfoTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.ListUnspent(mCard.getWallet()));
}
RateInfoTask taskRate = new RateInfoTask(LoadedWallet.this);
ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "bitcoin", "bitcoin");
taskRate.execute(rate);
} else if (mCard.getBlockchain() == Blockchain.BitcoinCash || mCard.getBlockchain() == Blockchain.BitcoinCashTestNet) {
SharedData data = new SharedData(SharedData.COUNT_REQUEST);
for (int i = 0; i < data.allRequest; ++i) {
String nodeAddress = Objects.requireNonNull(engine).GetNextNode(mCard);
int nodePort = engine.GetNextNodePort(mCard);
UpdateWalletInfoTask connectTaskEx = new UpdateWalletInfoTask(LoadedWallet.this, nodeAddress, nodePort, data);
connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet()));
}
String nodeAddress = Objects.requireNonNull(engine).GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
UpdateWalletInfoTask updateWalletInfoTask = new UpdateWalletInfoTask(LoadedWallet.this,nodeAddress, nodePort, data);
updateTasks.add(updateWalletInfoTask);
updateWalletInfoTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.ListUnspent(mCard.getWallet())
// ElectrumRequest.ListHistory(mCard.getWallet())
);
RateInfoTask taskRate = new RateInfoTask(LoadedWallet.this);
ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "bitcoin-cash", "bitcoin-cash");
taskRate.execute(rate);
} else if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet) {
ETHRequestTask updateETH = new ETHRequestTask(LoadedWallet.this, mCard.getBlockchain());
InfuraRequest reqETH = InfuraRequest.GetBalance(mCard.getWallet());
reqETH.setID(67);
reqETH.setBlockchain(mCard.getBlockchain());
InfuraRequest reqNonce = InfuraRequest.GetOutTransactionCount(mCard.getWallet());
reqNonce.setID(67);
reqNonce.setBlockchain(mCard.getBlockchain());
updateETH.execute(reqETH, reqNonce);
RateInfoTask taskRate = new RateInfoTask(LoadedWallet.this);
ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "ic_logo_ethereum", "ic_logo_ethereum");
taskRate.execute(rate);
} else if (mCard.getBlockchain() == Blockchain.Token) {
ETHRequestTask updateETH = new ETHRequestTask(LoadedWallet.this, mCard.getBlockchain());
InfuraRequest reqETH = InfuraRequest.GetTokenBalance(mCard.getWallet(), Objects.requireNonNull(engine).GetContractAddress(mCard), engine.GetTokenDecimals(mCard));
reqETH.setID(67);
reqETH.setBlockchain(mCard.getBlockchain());
InfuraRequest reqBalance = InfuraRequest.GetBalance(mCard.getWallet());
reqBalance.setID(67);
reqBalance.setBlockchain(mCard.getBlockchain());
InfuraRequest reqNonce = InfuraRequest.GetOutTransactionCount(mCard.getWallet());
reqNonce.setID(67);
reqNonce.setBlockchain(mCard.getBlockchain());
updateETH.execute(reqETH, reqNonce, reqBalance);
RateInfoTask taskRate = new RateInfoTask(LoadedWallet.this);
ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "basic-attention-token", "ic_logo_ethereum");
taskRate.execute(rate);
}
if (needResendTX) {
sendTransaction(LastSignStorage.getTxForSend(mCard.getWallet()));
}
}
@Override
public void onTagDiscovered(Tag tag) {
startVerify(tag);
}
public Intent prepareResultIntent() {
Intent data = new Intent();
data.putExtra("UID", mCard.getUID());
data.putExtra("Card", mCard.getAsBundle());
return data;
}
@Override
public void OnReadStart(CardProtocol cardProtocol) {
progressBar.post(() -> {
rlProgressBar.setVisibility(View.VISIBLE);
//progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(5);
});
}
@Override
public void OnReadFinish(final CardProtocol cardProtocol) {
verifyCardTask = null;
if (cardProtocol != null) {
if (cardProtocol.getError() == null) {
progressBar.post(() -> {
rlProgressBar.setVisibility(View.GONE);
progressBar.setProgress(100);
progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN));
mCardProtocol = cardProtocol;
// Log.i(TAG, "scanTimes " + scanTimes);
if (scanTimes > 0)
openVerifyCard(mCardProtocol);
scanTimes++;
//addCard(cardProtocol.getCard());
});
} else {
// remove last UIDs because of error and no card read
progressBar.post(() -> {
lastReadSuccess = false;
if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) {
if (!NoExtendedLengthSupportDialog.allreadyShowed) {
new NoExtendedLengthSupportDialog().show(Objects.requireNonNull(getActivity()).getFragmentManager(), NoExtendedLengthSupportDialog.TAG);
}
} else {
Toast.makeText(getContext(), R.string.try_to_scan_again, Toast.LENGTH_SHORT).show();
}
progressBar.setProgress(100);
progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));
});
}
}
progressBar.postDelayed(() -> {
try {
rlProgressBar.setVisibility(View.GONE);
progressBar.setProgress(0);
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
progressBar.setVisibility(View.INVISIBLE);
} catch (Exception e) {
e.printStackTrace();
}
}, 500);
}
@Override
public void OnReadProgress(CardProtocol protocol, final int progress) {
progressBar.post(() -> progressBar.setProgress(progress));
}
@Override
public void OnReadCancel() {
verifyCardTask = null;
progressBar.postDelayed(() -> {
try {
rlProgressBar.setVisibility(View.GONE);
progressBar.setProgress(0);
progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY));
progressBar.setVisibility(View.INVISIBLE);
} catch (Exception e) {
e.printStackTrace();
}
}, 500);
}
@Override
public void OnReadWait(int msec) {
WaitSecurityDelayDialog.OnReadWait(Objects.requireNonNull(getActivity()), msec);
}
@Override
public void OnReadBeforeRequest(int timeout) {
WaitSecurityDelayDialog.onReadBeforeRequest(Objects.requireNonNull(getActivity()), timeout);
}
@Override
public void OnReadAfterRequest() {
WaitSecurityDelayDialog.onReadAfterRequest(Objects.requireNonNull(getActivity()));
}
public void updateViews() {
try {
if (timerHideErrorAndMessage != null) {
timerHideErrorAndMessage.cancel();
timerHideErrorAndMessage = null;
}
tvCardID.setText(mCard.getCIDDescription());
if ((mCard.getError() == null || mCard.getError().isEmpty())) {
tvError.setVisibility(View.GONE);
tvError.setText("");
} else {
tvError.setVisibility(View.VISIBLE);
tvError.setText(mCard.getError());
}
boolean needResendTX = LastSignStorage.getNeedTxSend(mCard.getWallet());
if ((mCard.getMessage() == null || mCard.getMessage().isEmpty()) && !needResendTX) {
tvMessage.setText("");
tvMessage.setVisibility(View.GONE);
} else {
if (needResendTX) {
//tvMessage.setText(R.string.sending_cached_transaction);
} else {
tvMessage.setText(mCard.getMessage());
}
tvMessage.setVisibility(View.VISIBLE);
}
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
if (engine.HasBalanceInfo(mCard) || mCard.getOfflineBalance() == null) {
if (mCard.getBlockchain() == Blockchain.Token) {
Spanned html = Html.fromHtml(engine.GetBalanceWithAlter(mCard));
tvBalance.setText(html);
} else {
tvBalance.setText(engine.GetBalanceWithAlter(mCard));
}
tvBalanceEquivalent.setText(engine.GetBalanceEquivalent(mCard));
tvOffline.setVisibility(View.INVISIBLE);
} else {
String offlineAmount = engine.ConvertByteArrayToAmount(mCard, mCard.getOfflineBalance());
if (mCard.getBlockchain() == Blockchain.Token) {
tvBalance.setText(R.string.not_implemented);
} else {
tvBalance.setText(engine.GetAmountDescription(mCard, offlineAmount));
}
tvBalanceEquivalent.setText(engine.GetAmountEqualentDescriptor(mCard, offlineAmount));
tvOffline.setVisibility(View.VISIBLE);
}
if (!mCard.getAmountEquivalentDescriptionAvailable()) {
//tvBalanceEquivalent.setError("Service unavailable");
} else {
tvBalanceEquivalent.setError(null);
}
tvWallet.setText(mCard.getWallet());
tvInputs.setText(mCard.getInputsDescription());
if (mCard.getLastInputDescription().contains("awaiting"))
tvInputs.setTextColor(ContextCompat.getColor(Objects.requireNonNull(getContext()), R.color.not_confirmed));
else if (mCard.getLastInputDescription().contains("None"))
tvInputs.setTextColor(ContextCompat.getColor(Objects.requireNonNull(getContext()), R.color.primary_dark));
else
tvInputs.setTextColor(ContextCompat.getColor(Objects.requireNonNull(getContext()), R.color.confirmed));
tvBlockchain.setText(mCard.getBlockchainName());
ivBlockchain.setImageResource(mCard.getBlockchain().getImageResource(getContext(), mCard.getTokenSymbol()));
if (tvValidationNode != null) {
tvValidationNode.setText(mCard.getValidationNodeDescription());
}
if (mCard.useDefaultPIN1()) {
ivPIN.setImageResource(R.drawable.unlock_pin1);
ivPIN.setOnClickListener(v -> Toast.makeText(getContext(), R.string.this_banknote_protected_default_PIN1_code, Toast.LENGTH_LONG).show());
} else {
ivPIN.setImageResource(R.drawable.lock_pin1);
ivPIN.setOnClickListener(v -> Toast.makeText(getContext(), R.string.this_banknote_protected_user_PIN1_code, Toast.LENGTH_LONG).show());
}
if (mCard.getPauseBeforePIN2() > 0 && (mCard.useDefaultPIN2() || !mCard.useSmartSecurityDelay())) {
ivPIN2orSecurityDelay.setImageResource(R.drawable.timer);
ivPIN2orSecurityDelay.setOnClickListener(v -> Toast.makeText(getContext(), String.format("This banknote will enforce %.0f seconds security delay for all operations requiring PIN2 code", mCard.getPauseBeforePIN2() / 1000.0), Toast.LENGTH_LONG).show());
} else if (mCard.useDefaultPIN2()) {
ivPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2);
ivPIN2orSecurityDelay.setOnClickListener(v -> Toast.makeText(getContext(), R.string.this_banknote_protected_default_PIN2_code, Toast.LENGTH_LONG).show());
} else {
ivPIN2orSecurityDelay.setImageResource(R.drawable.lock_pin2);
ivPIN2orSecurityDelay.setOnClickListener(v -> Toast.makeText(getContext(), R.string.this_banknote_protected_user_PIN2_code, Toast.LENGTH_LONG).show());
}
if (mCard.useDevelopersFirmware()) {
ivDeveloperVersion.setImageResource(R.drawable.ic_developer_version);
ivDeveloperVersion.setVisibility(View.VISIBLE);
ivDeveloperVersion.setOnClickListener(v -> Toast.makeText(getContext(), R.string.unlocked_banknote_only_development_use, Toast.LENGTH_LONG).show());
} else {
ivDeveloperVersion.setVisibility(View.INVISIBLE);
}
if (mCard.hasBalanceInfo())
btnExtract.setEnabled(true);
else
btnExtract.setEnabled(false);
tvIssuer.setText(mCard.getIssuerDescription());
timerHideErrorAndMessage = new Timer();
timerHideErrorAndMessage.schedule(new TimerTask() {
@Override
public void run() {
tvError.post(() -> {
tvMessage.setVisibility(View.GONE);
tvError.setVisibility(View.GONE);
mCard.setError(null);
mCard.setMessage(null);
});
}
}, 5000);
if (mCard.isReusable()) {
tvHeader.setText(R.string.reusable_wallet);
tvCaution.setVisibility(View.GONE);
} else {
if (mCard.getMaxSignatures() == mCard.getRemainingSignatures()) {
tvHeader.setText(R.string.banknote);
tvCaution.setVisibility(View.GONE);
} else {
tvHeader.setText(R.string.not_transferable_banknote);
tvCaution.setVisibility(View.VISIBLE);
}
}
if (mCard.useDevelopersFirmware()) {
tvHeader.setText(R.string.developer_kit);
tvCaution.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void errorOnUpdate(String message) {
// mCard.setError(getString(R.string.cannot_obtain_data_from_blockchain));
// updateViews();
}
private void openVerifyCard(CardProtocol cardProtocol) {
Intent intent = new Intent(getContext(), VerifyCardActivity.class);
intent.putExtra("UID", cardProtocol.getCard().getUID());
intent.putExtra("Card", cardProtocol.getCard().getAsBundle());
startActivityForResult(intent, REQUEST_CODE_VERIFY_CARD);
}
private void startVerify(Tag tag) {
try {
final IsoDep isoDep = IsoDep.get(tag);
if (isoDep == null) {
throw new CardProtocol.TangemException(getString(R.string.wrong_tag_err));
}
byte UID[] = tag.getId();
String sUID = Util.byteArrayToHexString(UID);
if (!mCard.getUID().equals(sUID)) {
Log.d(TAG, "Invalid UID: " + sUID);
mNfcManager.ignoreTag(isoDep.getTag());
return;
} else {
Log.v(TAG, "UID: " + sUID);
}
if (lastReadSuccess) {
isoDep.setTimeout(1000);
} else {
isoDep.setTimeout(65000);
}
verifyCardTask = new VerifyCardTask(getContext(), mCard, mNfcManager, isoDep, this);
verifyCardTask.start();
// Log.i(TAG, "onTagDiscovered " + Arrays.toString(tag.getId()));
} catch (Exception e) {
e.printStackTrace();
}
}
private void doShareWallet(boolean useURI) {
if (useURI) {
String txtShare = CoinEngineFactory.Create(mCard.getBlockchain()).getShareWalletURI(mCard).toString();
//String txtShare = Blockchain.getShareWalletURI(mCard).toString();
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, "Wallet address");
intent.putExtra(Intent.EXTRA_TEXT, txtShare);
PackageManager packageManager = Objects.requireNonNull(getActivity()).getPackageManager();
List activities = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL);
boolean isIntentSafe = activities.size() > 0;
if (isIntentSafe) {
String title = getString(R.string.share_wallet_address_with);
// create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// verify the intent will resolve to at least one activity
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(chooser);
}
} else {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE);
Objects.requireNonNull(clipboard).setPrimaryClip(ClipData.newPlainText(txtShare, txtShare));
Toast.makeText(getContext(), R.string.copied_clipboard, Toast.LENGTH_LONG).show();
}
} else {
String txtShare = mCard.getWallet();
ClipboardManager clipboard = (ClipboardManager) Objects.requireNonNull(getActivity()).getSystemService(CLIPBOARD_SERVICE);
Objects.requireNonNull(clipboard).setPrimaryClip(ClipData.newPlainText(txtShare, txtShare));
Toast.makeText(getContext(), R.string.copied_clipboard, Toast.LENGTH_LONG).show();
}
}
private void sendTransaction(String tx) {
CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain());
if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) {
ETHRequestTask task = new ETHRequestTask(LoadedWallet.this, mCard.getBlockchain());
InfuraRequest req = InfuraRequest.SendTransaction(mCard.getWallet(), tx);
req.setID(67);
req.setBlockchain(mCard.getBlockchain());
task.execute(req);
} else if (mCard.getBlockchain() == Blockchain.Bitcoin || mCard.getBlockchain() == Blockchain.BitcoinTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
UpdateWalletInfoTask connectTask = new UpdateWalletInfoTask(LoadedWallet.this, nodeAddress, nodePort);
connectTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.Broadcast(mCard.getWallet(), tx));
} else if (mCard.getBlockchain() == Blockchain.BitcoinCash || mCard.getBlockchain() == Blockchain.BitcoinCashTestNet) {
String nodeAddress = engine.GetNode(mCard);
int nodePort = engine.GetNodePort(mCard);
UpdateWalletInfoTask connectTask = new UpdateWalletInfoTask(LoadedWallet.this, nodeAddress, nodePort);
connectTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.Broadcast(mCard.getWallet(), tx));
}
}
private void startSwapPINActivity() {
Intent intent = new Intent(getContext(), SwapPINActivity.class);
intent.putExtra("UID", mCard.getUID());
intent.putExtra("Card", mCard.getAsBundle());
intent.putExtra("newPIN", newPIN);
intent.putExtra("newPIN2", newPIN2);
startActivityForResult(intent, REQUEST_CODE_SWAP_PIN);
}
}