Updated on 2026-08-14
This commit is contained in:
parent
6d3ab223ec
commit
c577dae7a1
9 changed files with 451 additions and 525 deletions
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<TangemCard.UnspentTransaction> rawTxList = mCard.getUnspentTransactions();
|
||||
byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes;
|
||||
|
||||
// Collect unspent
|
||||
ArrayList<UnspentOutputInfo> 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<ByteArray>(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("?")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -20,7 +19,7 @@
|
|||
android:textSize="@dimen/text_size_large"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/llPayment"
|
||||
|
|
@ -29,7 +28,8 @@
|
|||
android:background="@color/btn_light"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingLeft="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="8dp"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
|
|
@ -211,7 +211,6 @@
|
|||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<info.hoang8f.android.segmented.SegmentedGroup
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/rgFee"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -302,7 +301,7 @@
|
|||
android:textSize="@dimen/text_size_1_small"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@+id/tvCurrency2"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
|
|
@ -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" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
|
|
@ -333,6 +332,6 @@
|
|||
android:visibility="invisible"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/llFee"/>
|
||||
app:layout_constraintTop_toTopOf="@+id/llFee" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
|
@ -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" />
|
||||
|
||||
</GridLayout>
|
||||
|
|
|
|||
|
|
@ -9,12 +9,11 @@
|
|||
<color name="primary">#616161</color>
|
||||
<color name="primary_dark">@color/bg_material_dark</color>
|
||||
|
||||
<color name="accent">#000000</color>
|
||||
<color name="white">@android:color/white</color>
|
||||
<color name="black">#000000</color>
|
||||
<color name="bg_separator">#FFBABABA</color>
|
||||
<color name="text_normal">#FF505050</color>
|
||||
<color name="msg_send">@color/accent</color>
|
||||
<color name="msg_send">@color/black</color>
|
||||
<color name="msg_rcv">#4a763d</color>
|
||||
<color name="msg_okay">#BF7FF27F</color>
|
||||
<color name="msg_err">#BFFF4444</color>
|
||||
|
|
|
|||
|
|
@ -166,6 +166,13 @@
|
|||
<string name="minimal">Minimal</string>
|
||||
<string name="normal">Normal</string>
|
||||
<string name="priority">Priority</string>
|
||||
<string name="the_obtained_data_is_outdated_try_again">The obtained data is outdated! Try again</string>
|
||||
<string name="cannot_reach_current_active_blockchain_node_try_again">Cannot reach current active blockchain node. Try again</string>
|
||||
<string name="cannot_check_balance_no_connection_with_blockchain_nodes">Cannot check balance! No connection with blockchain nodes</string>
|
||||
<string name="the_wallet_is_empty">The wallet is empty</string>
|
||||
<string name="please_wait_for_confirmation_of_incoming_transaction">Please wait for confirmation of incoming transaction</string>
|
||||
<string name="fee_exceeds_payment_amount_enter_correct_value_and_repeat_sending">Fee exceeds payment amount. Enter correct value and repeat sending.</string>
|
||||
<string name="pin_2_is_required_to_sign_the_payment">PIN2 is required to sign the payment</string>
|
||||
|
||||
<!-- EmptyWalletActivity -->
|
||||
<string name="wallet_has_not_been_yet_created">Wallet hasn\'t been yet created</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue