diff --git a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectFeeTask.java b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectFeeTask.java index 6c498f4490..55bc85a9d9 100644 --- a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectFeeTask.java +++ b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectFeeTask.java @@ -45,11 +45,11 @@ public class ConnectFeeTask extends FeeTask { if (errCounter >= sharedCounter.allRequest) { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } } else { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } @@ -58,7 +58,7 @@ public class ConnectFeeTask extends FeeTask { } if (minFeeRate == 0) { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! Wrong data received from the node"); return; } @@ -75,50 +75,50 @@ public class ConnectFeeTask extends FeeTask { if (sharedCounter != null) { int errCounter = sharedCounter.errorRequest.incrementAndGet(); if (errCounter >= sharedCounter.allRequest) { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } } else { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } return; } - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); float finalFee = (float) minFeeRate / (float) 10000; finalFee = Math.round(finalFee) / (float) 10000; - if ((request.getBlockCount() == FeeRequest.MINIMAL) && (confirmPaymentActivity.minFee == null)) { - confirmPaymentActivity.minFee = String.valueOf(finalFee); - confirmPaymentActivity.minFeeInInternalUnits = confirmPaymentActivity.mCard.InternalUnitsFromString(String.valueOf(finalFee)); - } else if ((request.getBlockCount() == FeeRequest.NORMAL) && (confirmPaymentActivity.normalFee == null)) { - confirmPaymentActivity.normalFee = String.valueOf(finalFee); - } else if ((request.getBlockCount() == FeeRequest.PRIORITY) && (confirmPaymentActivity.maxFee == null)) { - confirmPaymentActivity.maxFee = String.valueOf(finalFee); + if ((request.getBlockCount() == FeeRequest.MINIMAL) && (confirmPaymentActivity.getMinFee() == null)) { + confirmPaymentActivity.setMinFee(String.valueOf(finalFee)); + confirmPaymentActivity.setMinFeeInInternalUnits(confirmPaymentActivity.getCard().InternalUnitsFromString(String.valueOf(finalFee))); + } else if ((request.getBlockCount() == FeeRequest.NORMAL) && (confirmPaymentActivity.getNormalFee() == null)) { + confirmPaymentActivity.setNormalFee(String.valueOf(finalFee)); + } else if ((request.getBlockCount() == FeeRequest.PRIORITY) && (confirmPaymentActivity.getMaxFee() == null)) { + confirmPaymentActivity.setMaxFee(String.valueOf(finalFee)); } - confirmPaymentActivity.doSetFee(confirmPaymentActivity.rgFee.getCheckedRadioButtonId()); + confirmPaymentActivity.doSetFee(confirmPaymentActivity.getRgFee().getCheckedRadioButtonId()); - confirmPaymentActivity.etFee.setError(null); - confirmPaymentActivity.feeRequestSuccess = true; - if (confirmPaymentActivity.feeRequestSuccess && confirmPaymentActivity.balanceRequestSuccess) { - confirmPaymentActivity.btnSend.setVisibility(View.VISIBLE); + confirmPaymentActivity.getEtFee().setError(null); + confirmPaymentActivity.setFeeRequestSuccess(true); + if (confirmPaymentActivity.getFeeRequestSuccess() && confirmPaymentActivity.getBalanceRequestSuccess()) { + confirmPaymentActivity.getBtnSend().setVisibility(View.VISIBLE); } - confirmPaymentActivity.dtVerifyed = new Date(); + confirmPaymentActivity.setDtVerified(new Date()); } else { if (sharedCounter != null) { int errCounter = sharedCounter.errorRequest.incrementAndGet(); if (errCounter >= sharedCounter.allRequest) { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } } else { - confirmPaymentActivity.progressBar.setVisibility(View.INVISIBLE); + confirmPaymentActivity.getProgressBar().setVisibility(View.INVISIBLE); confirmPaymentActivity.finishActivityWithError(Activity.RESULT_CANCELED, "Cannot calculate fee! No connection with blockchain nodes"); } } diff --git a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectTask.java b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectTask.java index 00dbe7f15a..f5f28f2d06 100644 --- a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectTask.java +++ b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ConnectTask.java @@ -42,34 +42,34 @@ public class ConnectTask extends ElectrumTask { if (request.error == null) { if (request.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { - confirmPaymentActivity.etFee.setText("--"); + confirmPaymentActivity.getEtFee().setText("--"); //String mWalletAddress = request.getParams().getString(0); - if ((request.getResult().getInt("confirmed") + request.getResult().getInt("unconfirmed")) / confirmPaymentActivity.mCard.getBlockchain().getMultiplier() * 1000000.0 < Float.parseFloat(confirmPaymentActivity.etAmount.getText().toString())) { - confirmPaymentActivity.etFee.setError("Not enough funds"); + if ((request.getResult().getInt("confirmed") + request.getResult().getInt("unconfirmed")) / confirmPaymentActivity.getCard().getBlockchain().getMultiplier() * 1000000.0 < Float.parseFloat(confirmPaymentActivity.getEtAmount().getText().toString())) { + confirmPaymentActivity.getEtFee().setError("Not enough funds"); if (sharedCounter == null) { - confirmPaymentActivity.balanceRequestSuccess = false; - confirmPaymentActivity.btnSend.setVisibility(View.INVISIBLE); - confirmPaymentActivity.dtVerifyed = null; - confirmPaymentActivity.nodeCheck = false; + confirmPaymentActivity.setBalanceRequestSuccess(false); + confirmPaymentActivity.getBtnSend().setVisibility(View.INVISIBLE); + confirmPaymentActivity.setDtVerified(null); + confirmPaymentActivity.setNodeCheck(false); } else { int errCounter = sharedCounter.errorRequest.incrementAndGet(); if (errCounter >= sharedCounter.allRequest) { - confirmPaymentActivity.balanceRequestSuccess = false; - confirmPaymentActivity.btnSend.setVisibility(View.INVISIBLE); - confirmPaymentActivity.dtVerifyed = null; - confirmPaymentActivity.nodeCheck = false; + confirmPaymentActivity.setBalanceRequestSuccess(false); + confirmPaymentActivity.getBtnSend().setVisibility(View.INVISIBLE); + confirmPaymentActivity.setDtVerified(null); + confirmPaymentActivity.setNodeCheck(false); } } } else { - confirmPaymentActivity.etFee.setError(null); - confirmPaymentActivity.balanceRequestSuccess = true; - if (confirmPaymentActivity.feeRequestSuccess && confirmPaymentActivity.balanceRequestSuccess) { - confirmPaymentActivity.btnSend.setVisibility(View.VISIBLE); + confirmPaymentActivity.getEtFee().setError(null); + confirmPaymentActivity.setBalanceRequestSuccess(true); + if (confirmPaymentActivity.getFeeRequestSuccess() && confirmPaymentActivity.getBalanceRequestSuccess()) { + confirmPaymentActivity.getBtnSend().setVisibility(View.VISIBLE); } - confirmPaymentActivity.dtVerifyed = new Date(); - confirmPaymentActivity.nodeCheck = true; + confirmPaymentActivity.setDtVerified(new Date()); + confirmPaymentActivity.setNodeCheck(true); } } catch (JSONException e) { if (sharedCounter != null) { @@ -85,7 +85,7 @@ public class ConnectTask extends ElectrumTask { } } else if (request.isMethod(ElectrumRequest.METHOD_GetFee)) { if (request.getResultString() == "-1") { - confirmPaymentActivity.etFee.setText("3"); + confirmPaymentActivity.getEtFee().setText("3"); } } } else { diff --git a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ETHRequestTask.java b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ETHRequestTask.java index 529ac48b2b..39e4300200 100644 --- a/app/src/main/java/com/tangem/data/network/task/confirm_payment/ETHRequestTask.java +++ b/app/src/main/java/com/tangem/data/network/task/confirm_payment/ETHRequestTask.java @@ -39,21 +39,20 @@ public class ETHRequestTask extends InfuraTask { gasPrice = gasPrice.substring(2); BigInteger l = new BigInteger(gasPrice, 16); - BigInteger m = confirmPaymentActivity.mCard.getBlockchain() == Blockchain.Token ? BigInteger.valueOf(55000) : BigInteger.valueOf(21000); + BigInteger m = confirmPaymentActivity.getCard().getBlockchain() == Blockchain.Token ? BigInteger.valueOf(55000) : BigInteger.valueOf(21000); l = l.multiply(m); - String feeInGwei = confirmPaymentActivity.mCard.getAmountInGwei(String.valueOf(l)); + String feeInGwei = confirmPaymentActivity.getCard().getAmountInGwei(String.valueOf(l)); - confirmPaymentActivity.minFee = feeInGwei; - confirmPaymentActivity.maxFee = feeInGwei; - confirmPaymentActivity.normalFee = feeInGwei; - confirmPaymentActivity.etFee.setText(feeInGwei); - confirmPaymentActivity.etFee.setError(null); - confirmPaymentActivity.btnSend.setVisibility(View.VISIBLE); - confirmPaymentActivity.feeRequestSuccess = true; - confirmPaymentActivity.balanceRequestSuccess = true; - - confirmPaymentActivity.dtVerifyed = new Date(); - confirmPaymentActivity.minFeeInInternalUnits = confirmPaymentActivity.mCard.InternalUnitsFromString(feeInGwei); + confirmPaymentActivity.setMinFee(feeInGwei); + confirmPaymentActivity.setMaxFee(feeInGwei); + confirmPaymentActivity.setNormalFee(feeInGwei); + confirmPaymentActivity.getEtFee().setText(feeInGwei); + confirmPaymentActivity.getEtFee().setError(null); + confirmPaymentActivity.getBtnSend().setVisibility(View.VISIBLE); + confirmPaymentActivity.setFeeRequestSuccess(true); + confirmPaymentActivity.setBalanceRequestSuccess(true); + confirmPaymentActivity.setDtVerified(new Date()); + confirmPaymentActivity.setMinFeeInInternalUnits(confirmPaymentActivity.getCard().InternalUnitsFromString(feeInGwei)); } catch (JSONException e) { e.printStackTrace(); @@ -69,4 +68,5 @@ public class ETHRequestTask extends InfuraTask { } } } -} + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java deleted file mode 100644 index f205adb46f..0000000000 --- a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java +++ /dev/null @@ -1,461 +0,0 @@ -package com.tangem.presentation.activity; - -import android.app.Activity; -import android.content.Intent; -import android.nfc.NfcAdapter; -import android.nfc.Tag; -import android.os.AsyncTask; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.text.Editable; -import android.text.Html; -import android.text.Spanned; -import android.text.TextWatcher; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.RadioGroup; -import android.widget.TextView; -import android.widget.Toast; - -import com.tangem.data.network.request.ElectrumRequest; -import com.tangem.data.network.request.FeeRequest; -import com.tangem.data.network.request.InfuraRequest; -import com.tangem.data.network.task.confirm_payment.ConnectFeeTask; -import com.tangem.data.network.task.confirm_payment.ConnectTask; -import com.tangem.data.network.task.confirm_payment.ETHRequestTask; -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.SharedData; -import com.tangem.domain.wallet.TangemCard; -import com.tangem.domain.wallet.Transaction; -import com.tangem.domain.wallet.UnspentOutputInfo; -import com.tangem.util.BTCUtils; -import com.tangem.util.DerEncodingUtil; -import com.tangem.util.FormatUtil; -import com.tangem.util.Util; -import com.tangem.wallet.R; - -import java.io.IOException; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.List; - -public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback { - - private static final int REQUEST_CODE_SIGN_PAYMENT = 1; - private static final int REQUEST_CODE_REQUEST_PIN2 = 2; - public Button btnSend; - public boolean feeRequestSuccess = false; - public boolean balanceRequestSuccess = false; - private EditText etWallet; - // private TextView tvAmountEquivalent; - private TextView tvFeeEquivalent; - public EditText etAmount; - public EditText etFee; - private ImageView ivCamera; - public TangemCard mCard; - public RadioGroup rgFee; - public String minFee = null, maxFee = null, normalFee = null; - public Long minFeeInInternalUnits = 0L; - private NfcManager mNfcManager; - private int requestPIN2Count = 0; - public ProgressBar progressBar; - public boolean nodeCheck = false; - public Date dtVerifyed = null; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_confirm_payment); - - MainActivity.Companion.commonInit(getApplicationContext()); - mNfcManager = new NfcManager(this, this); - - mCard = new TangemCard(getIntent().getStringExtra("UID")); - mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); - - progressBar = findViewById(R.id.progressBar); - btnSend = findViewById(R.id.btnSend); - etWallet = findViewById(R.id.etWallet); - TextView tvCardID = findViewById(R.id.tvCardID); - TextView tvBalance = findViewById(R.id.tvBalance); - TextView tvCurrency = findViewById(R.id.tvCurrency); - TextView tvCurrency2 = findViewById(R.id.tvCurrency2); - etAmount = findViewById(R.id.etAmount); - etFee = findViewById(R.id.etFee); -// TextView tvBalanceEquivalent = findViewById(R.id.tvBalanceEquivalent); -// tvAmountEquivalent = findViewById(R.id.tvAmountEquivalent); - tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent); - ivCamera = findViewById(R.id.ivCamera); - rgFee = findViewById(R.id.rgFee); - - rgFee.setOnCheckedChangeListener((group, checkedId) -> doSetFee(checkedId)); - - etAmount.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { -// try { -// -// CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); -// tvAmountEquivalent.setText(engine.GetAmountEqualentDescriptor(mCard, etAmount.getText().toString())); -// if (!mCard.getAmountEquivalentDescriptionAvailable()) { -// tvAmountEquivalent.setError("Service unavailable"); -// } else { -// tvAmountEquivalent.setError(null); -// } -// } catch (Exception e) { -// e.printStackTrace(); -// tvAmountEquivalent.setText(""); -// } - } - - @Override - public void afterTextChanged(Editable s) { - - } - }); - - etFee.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - try { - - CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); - String eqFee = engine.EvaluteFeeEquivalent(mCard, etFee.getText().toString()); - tvFeeEquivalent.setText(eqFee); - - if (!mCard.getAmountEquivalentDescriptionAvailable()) { - tvFeeEquivalent.setError("Service unavailable"); - } else { - tvFeeEquivalent.setError(null); - } - } catch (Exception e) { - e.printStackTrace(); - tvFeeEquivalent.setText(""); - } - } - - @Override - public void afterTextChanged(Editable s) { - - } - }); - - CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); - //tvBalance.setText(engine.GetBalanceWithAlter(mCard)); - if (mCard.getBlockchain() == Blockchain.Token) { - Spanned html = Html.fromHtml(engine.GetBalanceWithAlter(mCard)); - tvBalance.setText(html); - } else { - tvBalance.setText(engine.GetBalanceWithAlter(mCard)); - } - etAmount.setText(getIntent().getStringExtra(SignPaymentActivity.EXTRA_AMOUNT)); - tvCurrency.setText(engine.GetBalanceCurrency(mCard)); - tvCurrency2.setText(engine.GetFeeCurrency()); - - tvCardID.setText(mCard.getCIDDescription()); - - //tvBalanceEquivalent.setText(mCard.getBalanceEquivalentDescription()); -// tvBalanceEquivalent.setText(engine.GetBalanceEquivalent(mCard)); -// if (!mCard.getAmountEquivalentDescriptionAvailable()) { -// tvBalanceEquivalent.setError("Service unavailable"); -// } else { -// tvBalanceEquivalent.setError(null); -// } - - etWallet.setText(getIntent().getStringExtra("Wallet")); - - etFee.setText("?"); - - btnSend.setVisibility(View.INVISIBLE); - feeRequestSuccess = false; - balanceRequestSuccess = false; - - btnSend.setOnClickListener(v -> { - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MINUTE, -1); - - if (dtVerifyed == null || dtVerifyed.before(calendar.getTime())) { - finishActivityWithError(Activity.RESULT_CANCELED, "The obtained data is outdated! Try again"); - return; - } - - CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain()); - - if (engineCoin.IsNeedCheckNode() && !nodeCheck) { - Toast.makeText(getBaseContext(), "Cannot reach current active blockchain node. Try again", Toast.LENGTH_LONG).show(); - return; - } - String txFee = etFee.getText().toString(); - String txAmount = etAmount.getText().toString(); - - - if (!engineCoin.HasBalanceInfo(mCard)) { - finishActivityWithError(Activity.RESULT_CANCELED, "Cannot check balance! No connection with blockchain nodes"); - return; - } else if (!engineCoin.IsBalanceNotZero(mCard)) { - finishActivityWithError(Activity.RESULT_CANCELED, "The wallet is empty"); - return; - } else if (!engineCoin.CheckUnspentTransaction(mCard)) { - //else if (mCard.getUnspentTransactions().size() == 0 && mCard.getBlockchain() != Blockchain.Ethereum) { - finishActivityWithError(Activity.RESULT_CANCELED, "Please wait for confirmation of incoming transaction"); - return; - } - - if (!engineCoin.CheckAmountValie(mCard, txAmount, txFee, minFeeInInternalUnits)) { - finishActivityWithError(Activity.RESULT_CANCELED, "Fee exceeds payment amount. Enter correct value and repeat sending."); - return; - } - - requestPIN2Count = 0; - Intent intent = new Intent(getBaseContext(), 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); - }); - - if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) { - ETHRequestTask task = new ETHRequestTask(ConfirmPaymentActivity.this, mCard.getBlockchain()); - InfuraRequest req = InfuraRequest.GetGasPrise(mCard.getWallet()); - req.setID(67); - req.setBlockchain(mCard.getBlockchain()); - rgFee.setEnabled(false); - task.execute(req); - - } else { - rgFee.setEnabled(true); - - SharedData data = new SharedData(SharedData.COUNT_REQUEST); - - CoinEngine engineCoin = CoinEngineFactory.Create(mCard.getBlockchain()); - - for (int i = 0; i < data.allRequest; ++i) { - - String nodeAddress = engineCoin.GetNextNode(mCard); - int nodePort = engineCoin.GetNextNodePort(mCard); - ConnectTask connectTaskEx = new ConnectTask(ConfirmPaymentActivity.this, nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet())); - } - -// String nodeAddress = engineCoin.GetNode(mCard); -// int nodePort = engineCoin.GetNodePort(mCard); -// ConnectTask connectTask = new ConnectTask(nodeAddress, nodePort, data); -// -// -// connectTask.execute(ElectrumRequest.GetFee(mCard.getWallet())); - - int calcSize = 256; - try { - calcSize = BuildSize(etWallet.getText().toString(), "0.00", etAmount.getText().toString()); - } catch (Exception ex) { - Log.e("Build Fee error", ex.getMessage()); - } - - mCard.resetFailedBalanceRequestCounter(); - SharedData sharedFee = new SharedData(SharedData.COUNT_REQUEST); - - progressBar.setVisibility(View.VISIBLE); - for (int i = 0; i < SharedData.COUNT_REQUEST; ++i) { - - ConnectFeeTask feeTask = new ConnectFeeTask(ConfirmPaymentActivity.this, sharedFee); - - feeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, - FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.NORMAL), - FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.MINIMAL), - FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.PRIORITY)); - } - } - } - - @Override - public void onResume() { - super.onResume(); - mNfcManager.onResume(); - } - - @Override - public void onPause() { - super.onPause(); - mNfcManager.onPause(); - } - - @Override - public void onStop() { - super.onStop(); - mNfcManager.onStop(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE_SIGN_PAYMENT) { - 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 (resultCode == SignPaymentActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { - requestPIN2Count++; - Intent intent = new Intent(getBaseContext(), 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); - return; - } - setResult(resultCode, data); - finish(); - } else if (requestCode == REQUEST_CODE_REQUEST_PIN2) { - if (resultCode == Activity.RESULT_OK) { - Intent intent = new Intent(getBaseContext(), SignPaymentActivity.class); - intent.putExtra("UID", mCard.getUID()); - intent.putExtra("Card", mCard.getAsBundle()); - intent.putExtra("Wallet", etWallet.getText().toString()); - intent.putExtra(SignPaymentActivity.EXTRA_AMOUNT, etAmount.getText().toString()); - intent.putExtra("Fee", etFee.getText().toString()); - startActivityForResult(intent, REQUEST_CODE_SIGN_PAYMENT); - } else { - Toast.makeText(getBaseContext(), "PIN2 is required to sign the payment", Toast.LENGTH_LONG).show(); - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_BACK: - Intent intent = new Intent(); -// intent.putExtra("message", "Operation canceled"); - setResult(Activity.RESULT_CANCELED, intent); - finish(); - return true; - } - return super.onKeyDown(keyCode, event); - } - - public void finishActivityWithError(int errorCode, String message) { - //Snackbar.make(etFee, message, Snackbar.LENGTH_LONG).show(); - Intent intent = new Intent(); - intent.putExtra("message", message); - setResult(errorCode, intent); - finish(); - } - - @Override - public void onTagDiscovered(Tag tag) { - try { - Log.w(getClass().getName(), "Ignore discovered tag!"); - mNfcManager.ignoreTag(tag); - } catch (IOException e) { - e.printStackTrace(); - } - } - - int BuildSize(String outputAddress, String outFee, String outAmount) throws Exception { - String myAddress = mCard.getWallet(); - String changeAddress = myAddress; //"n2eMqTT929pb1RDNuqEnxdaLau1rxy3efi"; - byte[] pbKey = mCard.getWalletPublicKey(); - byte[] pbComprKey = mCard.getWalletPublicKeyRar(); - - // Build script for our address - List rawTxList = mCard.getUnspentTransactions(); - byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; - - // Collect unspent - ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); - - long fullAmount = 0; - for (int i = 0; i < unspentOutputs.size(); ++i) { - fullAmount += unspentOutputs.get(i).value; - } - - // Get first unspent - UnspentOutputInfo outPut = unspentOutputs.get(0); - int outPutIndex = outPut.outputIndex; - - // get prev TX id; - String prevTXID = rawTxList.get(0).txID;//"f67b838d6e2c0c587f476f583843e93ff20368eaf96a798bdc25e01f53f8f5d2"; - - long fees = FormatUtil.ConvertStringToLong(outFee); - long amount = FormatUtil.ConvertStringToLong(outAmount); - amount = amount - fees; - - long change = fullAmount - fees - amount; - - if (amount + fees > fullAmount) { - throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)); - } - - byte[][] hashesForSign = new byte[unspentOutputs.size()][]; - - for (int i = 0; i < unspentOutputs.size(); ++i) { - byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change); - - byte[] hashData = Util.calculateSHA256(newTX); - byte[] doubleHashData = Util.calculateSHA256(hashData); - - Log.e("TX_BODY_1", BTCUtils.toHex(newTX)); - Log.e("TX_HASH_1", BTCUtils.toHex(hashData)); - Log.e("TX_HASH_2", BTCUtils.toHex(doubleHashData)); - - unspentOutputs.get(i).bodyDoubleHash = doubleHashData; - unspentOutputs.get(i).bodyHash = hashData; - - hashesForSign[i] = doubleHashData; - } - - byte[] signFromCard = new byte[64 * unspentOutputs.size()]; - - for (int i = 0; i < unspentOutputs.size(); ++i) { - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); - BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); - byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey); - unspentOutputs.get(i).scriptForBuild = encodingSign; - } - - byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); - - return realTX.length; - } - - public void doSetFee(int checkedRadioButtonId) { - switch (checkedRadioButtonId) { - case R.id.rbMinimalFee: - if (minFee != null) etFee.setText(minFee); - else etFee.setText("?"); - break; - case R.id.rbNormalFee: - if (normalFee != null) etFee.setText(normalFee); - else etFee.setText("?"); - break; - case R.id.rbMaximumFee: - if (maxFee != null) etFee.setText(maxFee); - else etFee.setText("?"); - break; - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt new file mode 100644 index 0000000000..2317d47a19 --- /dev/null +++ b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.kt @@ -0,0 +1,382 @@ +package com.tangem.presentation.activity + +import android.app.Activity +import android.content.Intent +import android.nfc.NfcAdapter +import android.nfc.Tag +import android.os.AsyncTask +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.text.Editable +import android.text.Html +import android.text.TextWatcher +import android.util.Log +import android.view.KeyEvent +import android.view.View +import android.widget.* +import com.tangem.data.network.request.ElectrumRequest +import com.tangem.data.network.request.FeeRequest +import com.tangem.data.network.request.InfuraRequest +import com.tangem.data.network.task.confirm_payment.ConnectFeeTask +import com.tangem.data.network.task.confirm_payment.ConnectTask +import com.tangem.data.network.task.confirm_payment.ETHRequestTask +import com.tangem.domain.cardReader.NfcManager +import com.tangem.domain.wallet.* +import com.tangem.util.BTCUtils +import com.tangem.util.DerEncodingUtil +import com.tangem.util.FormatUtil +import com.tangem.util.Util +import com.tangem.wallet.R +import kotlinx.android.synthetic.main.activity_confirm_payment.* +import java.io.IOException +import java.math.BigInteger +import java.util.* + +class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback { + companion object { + private const val REQUEST_CODE_SIGN_PAYMENT = 1 + private const val REQUEST_CODE_REQUEST_PIN2 = 2 + } + + private var nfcManager: NfcManager? = null + var card: TangemCard? = null + + var feeRequestSuccess = false + var balanceRequestSuccess = false + + private var tvFeeEquivalent: TextView? = null + var etAmount: EditText? = null + var etFee: EditText? = null + var rgFee: RadioGroup? = null + var progressBar: ProgressBar? = null + var btnSend: Button? = null + + var minFee: String? = null + var maxFee: String? = null + var normalFee: String? = null + var minFeeInInternalUnits: Long? = 0L + private var requestPIN2Count = 0 + var nodeCheck = false + var dtVerified: Date? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_confirm_payment) + + MainActivity.commonInit(applicationContext) + + nfcManager = NfcManager(this, this) + + card = TangemCard(intent.getStringExtra("UID")) + card!!.LoadFromBundle(intent.extras!!.getBundle("Card")) + + progressBar = findViewById(R.id.progressBar) + btnSend = findViewById(R.id.btnSend) + etAmount = findViewById(R.id.etAmount) + etFee = findViewById(R.id.etFee) + tvFeeEquivalent = findViewById(R.id.tvFeeEquivalent) + rgFee = findViewById(R.id.rgFee) + + val engine = CoinEngineFactory.Create(card!!.blockchain) + if (card!!.blockchain == Blockchain.Token) { + val html = Html.fromHtml(engine!!.GetBalanceWithAlter(card)) + tvBalance.text = html + } else + tvBalance.text = engine!!.GetBalanceWithAlter(card) + + etAmount!!.setText(intent.getStringExtra(SignPaymentActivity.EXTRA_AMOUNT)) + tvCurrency.text = engine.GetBalanceCurrency(card) + tvCurrency2.text = engine.GetFeeCurrency() + + tvCardID.text = card!!.cidDescription + + etWallet!!.setText(intent.getStringExtra("Wallet")) + + etFee!!.setText("?") + + btnSend!!.visibility = View.INVISIBLE + feeRequestSuccess = false + balanceRequestSuccess = false + + // 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 engine = CoinEngineFactory.Create(card!!.blockchain) + val eqFee = engine!!.EvaluteFeeEquivalent(card, etFee!!.text.toString()) + tvFeeEquivalent!!.text = eqFee + + if (!card!!.amountEquivalentDescriptionAvailable) { + tvFeeEquivalent!!.error = "Service unavailable" + } else { + tvFeeEquivalent!!.error = null + } + } catch (e: Exception) { + e.printStackTrace() + tvFeeEquivalent!!.text = "" + } + } + + override fun afterTextChanged(s: Editable) { + + } + }) + + btnSend!!.setOnClickListener { + val calendar = Calendar.getInstance() + calendar.add(Calendar.MINUTE, -1) + + if (dtVerified == null || dtVerified!!.before(calendar.time)) { + finishActivityWithError(Activity.RESULT_CANCELED, getString(R.string.the_obtained_data_is_outdated_try_again)) + return@setOnClickListener + } + + val engineCoin = CoinEngineFactory.Create(card!!.blockchain) + + 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 = etFee!!.text.toString() + val txAmount = etAmount!!.text.toString() + + if (!engineCoin.HasBalanceInfo(card)) { + finishActivityWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_check_balance_no_connection_with_blockchain_nodes)) + return@setOnClickListener + + } else if (!engineCoin.IsBalanceNotZero(card)) { + finishActivityWithError(Activity.RESULT_CANCELED, getString(R.string.the_wallet_is_empty)) + return@setOnClickListener + + } else if (!engineCoin.CheckUnspentTransaction(card)) { + finishActivityWithError(Activity.RESULT_CANCELED, getString(R.string.please_wait_for_confirmation_of_incoming_transaction)) + return@setOnClickListener + } + + if (!engineCoin.CheckAmountValie(card, txAmount, txFee, minFeeInInternalUnits)) { + finishActivityWithError(Activity.RESULT_CANCELED, getString(R.string.fee_exceeds_payment_amount_enter_correct_value_and_repeat_sending)) + return@setOnClickListener + } + + requestPIN2Count = 0 + val intent = Intent(baseContext, RequestPINActivity::class.java) + intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString()) + intent.putExtra("UID", card!!.uid) + intent.putExtra("Card", card!!.asBundle) + startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) + } + + if (card!!.blockchain == Blockchain.Ethereum || card!!.blockchain == Blockchain.EthereumTestNet || card!!.blockchain == Blockchain.Token) { + val task = ETHRequestTask(this@ConfirmPaymentActivity, card!!.blockchain) + val req = InfuraRequest.GetGasPrise(card!!.wallet) + req.id = 67 + req.setBlockchain(card!!.blockchain) + rgFee!!.isEnabled = false + task.execute(req) + + } else { + rgFee!!.isEnabled = true + val data = SharedData(SharedData.COUNT_REQUEST) + val engineCoin = CoinEngineFactory.Create(card!!.blockchain) + + for (i in 0 until data.allRequest) { + val nodeAddress = engineCoin!!.GetNextNode(card) + val nodePort = engineCoin.GetNextNodePort(card) + val connectTaskEx = ConnectTask(this@ConfirmPaymentActivity, nodeAddress, nodePort, data) + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(card!!.wallet)) + } + + var calcSize = 256 + try { + calcSize = buildSize(etWallet!!.text.toString(), "0.00", etAmount!!.text.toString()) + } catch (ex: Exception) { + Log.e("Build Fee error", ex.message) + } + + card!!.resetFailedBalanceRequestCounter() + val sharedFee = SharedData(SharedData.COUNT_REQUEST) + + progressBar!!.visibility = View.VISIBLE + for (i in 0 until SharedData.COUNT_REQUEST) { + val feeTask = ConnectFeeTask(this@ConfirmPaymentActivity, sharedFee) + feeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, + FeeRequest.GetFee(card!!.wallet, calcSize.toLong(), FeeRequest.NORMAL), + FeeRequest.GetFee(card!!.wallet, calcSize.toLong(), FeeRequest.MINIMAL), + FeeRequest.GetFee(card!!.wallet, calcSize.toLong(), FeeRequest.PRIORITY)) + } + } + } + + public override fun onResume() { + super.onResume() + nfcManager!!.onResume() + } + + public override fun onPause() { + super.onPause() + nfcManager!!.onPause() + } + + public override fun onStop() { + super.onStop() + nfcManager!!.onStop() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == REQUEST_CODE_SIGN_PAYMENT) { + 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 (resultCode == SignPaymentActivity.RESULT_INVALID_PIN && requestPIN2Count < 2) { + requestPIN2Count++ + val intent = Intent(baseContext, RequestPINActivity::class.java) + intent.putExtra("mode", RequestPINActivity.Mode.RequestPIN2.toString()) + intent.putExtra("UID", card!!.uid) + intent.putExtra("Card", card!!.asBundle) + startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2) + return + } + setResult(resultCode, data) + finish() + } else if (requestCode == REQUEST_CODE_REQUEST_PIN2) { + if (resultCode == Activity.RESULT_OK) { + val intent = Intent(baseContext, SignPaymentActivity::class.java) + intent.putExtra("UID", card!!.uid) + intent.putExtra("Card", card!!.asBundle) + intent.putExtra("Wallet", etWallet!!.text.toString()) + intent.putExtra(SignPaymentActivity.EXTRA_AMOUNT, etAmount!!.text.toString()) + intent.putExtra("Fee", etFee!!.text.toString()) + startActivityForResult(intent, REQUEST_CODE_SIGN_PAYMENT) + } else + Toast.makeText(baseContext, R.string.pin_2_is_required_to_sign_the_payment, 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) + } + + fun finishActivityWithError(errorCode: Int, message: String) { + val intent = Intent() + intent.putExtra("message", message) + setResult(errorCode, intent) + finish() + } + + override fun onTagDiscovered(tag: Tag) { + try { +// Log.w(getClass().getName(), "Ignore discovered tag!"); + nfcManager!!.ignoreTag(tag) + } catch (e: IOException) { + e.printStackTrace() + } + } + + @Throws(Exception::class) + internal fun buildSize(outputAddress: String, outFee: String, outAmount: String): Int { + val myAddress = card!!.wallet + val pbKey = card!!.walletPublicKey + val pbComprKey = card!!.walletPublicKeyRar + + // build script for our address + val rawTxList = card!!.unspentTransactions + val outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes + + // collect unspent + val unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend) + + var fullAmount: Long = 0 + for (i in unspentOutputs.indices) { + fullAmount += unspentOutputs[i].value + } + + // Get first unspent + val outPut = unspentOutputs[0] + val outPutIndex = outPut.outputIndex + + // get prev TX id; + val prevTXID = rawTxList[0].txID//"f67b838d6e2c0c587f476f583843e93ff20368eaf96a798bdc25e01f53f8f5d2"; + + val fees = FormatUtil.ConvertStringToLong(outFee) + var amount = FormatUtil.ConvertStringToLong(outAmount) + amount = amount - fees + + val change = fullAmount - fees - amount + + if (amount + fees > fullAmount) { + throw Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)) + } + + val hashesForSign = arrayOfNulls(unspentOutputs.size) + + for (i in unspentOutputs.indices) { + val newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, myAddress, unspentOutputs, i, amount, change) + + val hashData = Util.calculateSHA256(newTX) + val doubleHashData = Util.calculateSHA256(hashData) + + // Log.e("TX_BODY_1", BTCUtils.toHex(newTX)); + // Log.e("TX_HASH_1", BTCUtils.toHex(hashData)); + // Log.e("TX_HASH_2", BTCUtils.toHex(doubleHashData)); + + unspentOutputs[i].bodyDoubleHash = doubleHashData + unspentOutputs[i].bodyHash = hashData + + hashesForSign[i] = doubleHashData + } + + val signFromCard = ByteArray(64 * unspentOutputs.size) + + for (i in unspentOutputs.indices) { + val r = BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)) + val s = BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)) + val encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey) + unspentOutputs[i].scriptForBuild = encodingSign + } + + val realTX = BTCUtils.buildTXForSend(outputAddress, myAddress, unspentOutputs, amount, change) + + return realTX.size + } + + fun doSetFee(checkedRadioButtonId: Int) { + when (checkedRadioButtonId) { + R.id.rbMinimalFee -> + if (minFee != null) + etFee!!.setText(minFee) + else + etFee!!.setText("?") + R.id.rbNormalFee -> + if (normalFee != null) + etFee!!.setText(normalFee) + else + etFee!!.setText("?") + R.id.rbMaximumFee -> + if (maxFee != null) + etFee!!.setText(maxFee) + else + etFee!!.setText("?") + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_confirm_payment.xml b/app/src/main/res/layout/activity_confirm_payment.xml index f3f2b8a9ce..62d64011d6 100644 --- a/app/src/main/res/layout/activity_confirm_payment.xml +++ b/app/src/main/res/layout/activity_confirm_payment.xml @@ -1,6 +1,5 @@ - + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" /> @@ -319,7 +318,7 @@ android:textSize="@dimen/text_size_large" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent"/> + app:layout_constraintRight_toRightOf="parent" /> + app:layout_constraintTop_toTopOf="@+id/llFee" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_request_pin.xml b/app/src/main/res/layout/activity_request_pin.xml index c5cf1d007b..a987134c76 100644 --- a/app/src/main/res/layout/activity_request_pin.xml +++ b/app/src/main/res/layout/activity_request_pin.xml @@ -112,7 +112,7 @@ android:layout_marginTop="@dimen/pin_button_top_margin" android:fontFamily="@font/maax" android:text="@string/pin_back" - android:textColor="@color/accent" + android:textColor="@color/black" android:textSize="@dimen/text_size_pin" /> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0578685fed..980875891a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -9,12 +9,11 @@ #616161 @color/bg_material_dark - #000000 @android:color/white #000000 #FFBABABA #FF505050 - @color/accent + @color/black #4a763d #BF7FF27F #BFFF4444 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9b97507368..e6c1883ae3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -166,6 +166,13 @@ Minimal Normal Priority + The obtained data is outdated! Try again + Cannot reach current active blockchain node. Try again + Cannot check balance! No connection with blockchain nodes + The wallet is empty + Please wait for confirmation of incoming transaction + Fee exceeds payment amount. Enter correct value and repeat sending. + PIN2 is required to sign the payment Wallet hasn\'t been yet created