Updated on 2026-08-14
This commit is contained in:
parent
dae8c94c48
commit
e7c57f1e11
10 changed files with 530 additions and 337 deletions
|
|
@ -31,6 +31,21 @@ public class ServerApiInfura {
|
|||
public static final String INFURA_ETH_SEND_RAW_TRANSACTION = "eth_sendRawTransaction";
|
||||
public static final String INFURA_ETH_GAS_PRICE = "eth_gasPrice";
|
||||
|
||||
private int requestsCount=0;
|
||||
|
||||
public boolean hasRequests() {
|
||||
return requestsCount>0;
|
||||
}
|
||||
|
||||
private String error=null;
|
||||
public boolean isErrorOccured() {
|
||||
return error!=null;
|
||||
}
|
||||
|
||||
public void setErrorOccured(String error) {
|
||||
this.error=error;
|
||||
}
|
||||
|
||||
private InfuraBodyListener infuraBodyListener;
|
||||
|
||||
public interface InfuraBodyListener {
|
||||
|
|
@ -44,6 +59,7 @@ public class ServerApiInfura {
|
|||
}
|
||||
|
||||
public void infura(String method, int id, String wallet, String contract, String tx) {
|
||||
requestsCount++;
|
||||
InfuraApi infuraApi = App.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class);
|
||||
|
||||
InfuraBody infuraBody;
|
||||
|
|
@ -77,6 +93,7 @@ public class ServerApiInfura {
|
|||
@Override
|
||||
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> response) {
|
||||
if (response.code() == 200) {
|
||||
requestsCount--;
|
||||
infuraBodyListener.onSuccess(method, response.body());
|
||||
Log.i(TAG, "infura " + method + " onResponse " + response.code());
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -265,11 +265,19 @@ public abstract class CoinEngine {
|
|||
|
||||
}
|
||||
|
||||
|
||||
public interface BlockchainRequestsNotifications
|
||||
public interface BalanceAndUnspentTransactionsNotifications
|
||||
{
|
||||
void onComplete(Boolean success);
|
||||
boolean needTerminate();
|
||||
}
|
||||
public abstract void requestBalanceAndUnspentTransactions(BlockchainRequestsNotifications blockchainRequestsNotifications) throws Exception;
|
||||
public abstract void requestBalanceAndUnspentTransactions(BalanceAndUnspentTransactionsNotifications balanceAndUnspentTransactionsNotifications) throws Exception;
|
||||
|
||||
|
||||
public interface FeeRequestsNotifications
|
||||
{
|
||||
void onComplete(boolean success, Amount minFee, Amount normalFee, Amount maxFee);
|
||||
boolean needTerminate();
|
||||
}
|
||||
public abstract void requestFee(FeeRequestsNotifications feeRequestsNotifications, CoinEngine.Amount amount) throws Exception;
|
||||
|
||||
}
|
||||
|
|
@ -555,7 +555,7 @@ public class BtcCashEngine extends CoinEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void requestBalanceAndUnspentTransactions(BlockchainRequestsNotifications blockchainRequestsNotifications) throws Exception {
|
||||
public void requestBalanceAndUnspentTransactions(BalanceAndUnspentTransactionsNotifications balanceAndUnspentTransactionsNotifications) throws Exception {
|
||||
final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
|
||||
|
||||
ServerApiElectrum.ElectrumRequestDataListener electrumBodyListener = new ServerApiElectrum.ElectrumRequestDataListener() {
|
||||
|
|
@ -607,7 +607,7 @@ public class BtcCashEngine extends CoinEngine {
|
|||
Integer height = jsUnspent.getInt("height");
|
||||
String hash = jsUnspent.getString("tx_hash");
|
||||
if (height != -1) {
|
||||
if (!blockchainRequestsNotifications.needTerminate()) {
|
||||
if (!balanceAndUnspentTransactionsNotifications.needTerminate()) {
|
||||
serverApiElectrum.electrumRequestData(ctx, ElectrumRequest.getTransaction(walletAddress, hash));
|
||||
} else {
|
||||
serverApiElectrum.setErrorOccured("Terminated by user");
|
||||
|
|
@ -633,14 +633,14 @@ public class BtcCashEngine extends CoinEngine {
|
|||
}
|
||||
|
||||
if (!serverApiElectrum.hasRequests()) {
|
||||
blockchainRequestsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String method) {
|
||||
if (!serverApiElectrum.hasRequests()) {
|
||||
blockchainRequestsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.net.Uri;
|
|||
import android.text.InputFilter;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.data.network.ServerApiCommon;
|
||||
import com.tangem.tangemcard.reader.CardProtocol;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.Base58;
|
||||
|
|
@ -20,6 +21,7 @@ import com.tangem.util.CryptoUtil;
|
|||
import com.tangem.util.DecimalDigitsInputFilter;
|
||||
import com.tangem.util.DerEncodingUtil;
|
||||
import com.tangem.tangemcard.util.Util;
|
||||
import com.tangem.util.FormatUtil;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.data.network.ElectrumRequest;
|
||||
import com.tangem.data.network.ServerApiElectrum;
|
||||
|
|
@ -32,6 +34,7 @@ import org.json.JSONObject;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
|
@ -514,7 +517,7 @@ public class BtcEngine extends CoinEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void requestBalanceAndUnspentTransactions(BlockchainRequestsNotifications blockchainRequestsNotifications) {
|
||||
public void requestBalanceAndUnspentTransactions(BalanceAndUnspentTransactionsNotifications balanceAndUnspentTransactionsNotifications) {
|
||||
final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
|
||||
|
||||
ServerApiElectrum.ElectrumRequestDataListener electrumBodyListener = new ServerApiElectrum.ElectrumRequestDataListener() {
|
||||
|
|
@ -523,8 +526,7 @@ public class BtcEngine extends CoinEngine {
|
|||
if (electrumRequest.isMethod(ElectrumRequest.METHOD_GetBalance)) {
|
||||
try {
|
||||
String walletAddress = electrumRequest.getParams().getString(0);
|
||||
if( !walletAddress.equals(coinData.getWallet()))
|
||||
{
|
||||
if (!walletAddress.equals(coinData.getWallet())) {
|
||||
// todo - check
|
||||
throw new Exception("Invalid wallet address in answer!");
|
||||
}
|
||||
|
|
@ -537,8 +539,7 @@ public class BtcEngine extends CoinEngine {
|
|||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "FAIL METHOD_GetBalance JSONException");
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "FAIL METHOD_GetBalance Exception");
|
||||
}
|
||||
|
|
@ -568,9 +569,9 @@ public class BtcEngine extends CoinEngine {
|
|||
Integer height = jsUnspent.getInt("height");
|
||||
String hash = jsUnspent.getString("tx_hash");
|
||||
if (height != -1) {
|
||||
if( !blockchainRequestsNotifications.needTerminate() ) {
|
||||
if (!balanceAndUnspentTransactionsNotifications.needTerminate()) {
|
||||
serverApiElectrum.electrumRequestData(ctx, ElectrumRequest.getTransaction(walletAddress, hash));
|
||||
}else{
|
||||
} else {
|
||||
serverApiElectrum.setErrorOccured("Terminated by user");
|
||||
}
|
||||
}
|
||||
|
|
@ -593,17 +594,15 @@ public class BtcEngine extends CoinEngine {
|
|||
}
|
||||
}
|
||||
|
||||
if( !serverApiElectrum.hasRequests() )
|
||||
{
|
||||
blockchainRequestsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
if (!serverApiElectrum.hasRequests()) {
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String method) {
|
||||
if( !serverApiElectrum.hasRequests() )
|
||||
{
|
||||
blockchainRequestsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
if (!serverApiElectrum.hasRequests()) {
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiElectrum.isErrorOccured());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -614,7 +613,154 @@ public class BtcEngine extends CoinEngine {
|
|||
serverApiElectrum.electrumRequestData(ctx, ElectrumRequest.listUnspent(coinData.getWallet()));
|
||||
}
|
||||
|
||||
// @Override
|
||||
Integer buildSize(String outputAddress, String outFee, String outAmount) throws Exception {
|
||||
String myAddress = coinData.getWallet();
|
||||
byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
byte[] pbComprKey = ctx.getCard().getWalletPublicKeyRar();
|
||||
|
||||
// build script for our address
|
||||
List<BtcData.UnspentTransaction> rawTxList = coinData.getUnspentTransactions();
|
||||
byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes;
|
||||
|
||||
// collect unspent
|
||||
ArrayList<UnspentOutputInfo> unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend);
|
||||
|
||||
Long fullAmount = 0L;
|
||||
for (int i = 0; i < unspentOutputs.size(); i++) {
|
||||
fullAmount += unspentOutputs.get(i).value;
|
||||
}
|
||||
|
||||
// get first unspent
|
||||
// val outPut = unspentOutputs[0]
|
||||
// val outPutIndex = outPut.outputIndex
|
||||
|
||||
// get prev TX id;
|
||||
// val prevTXID = rawTxList[0].txID//"f67b838d6e2c0c587f476f583843e93ff20368eaf96a798bdc25e01f53f8f5d2";
|
||||
|
||||
Long fees = FormatUtil.ConvertStringToLong(outFee);
|
||||
Long amount = FormatUtil.ConvertStringToLong(outAmount);
|
||||
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, myAddress, 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[i].bodyDoubleHash = doubleHashData
|
||||
// unspentOutputs[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, myAddress, unspentOutputs, amount, change);
|
||||
|
||||
return realTX.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFee(FeeRequestsNotifications feeRequestsNotifications, CoinEngine.Amount amount) throws Exception {
|
||||
// request estimate fee listener
|
||||
// int calcSize = 256;
|
||||
// try {
|
||||
|
||||
final int calcSize = buildSize(coinData.getWallet(), "0.00", amount.toValueString());
|
||||
// } catch (Exception ex) {
|
||||
// Log.e(TAG,"Build Fee error: "+ ex.getMessage());
|
||||
// }
|
||||
|
||||
final ServerApiCommon serverApiCommon = new ServerApiCommon();
|
||||
|
||||
final ServerApiCommon.EstimateFeeListener estimateFeeListener = new ServerApiCommon.EstimateFeeListener() {
|
||||
@Override
|
||||
public void onSuccess(int blockCount, String estimateFeeResponse) {
|
||||
BigDecimal fee = new BigDecimal(estimateFeeResponse); // BTC per 1 kb
|
||||
|
||||
if (fee.equals(BigDecimal.ZERO)) {
|
||||
// progressBar.visibility = View.INVISIBLE
|
||||
if( !feeRequestsNotifications.needTerminate()) {
|
||||
serverApiCommon.estimateFee(blockCount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (calcSize != 0) {
|
||||
fee = fee.multiply(new BigDecimal(calcSize)).divide(new BigDecimal(1024)); // per Kb -> per byte
|
||||
} else {
|
||||
if( !feeRequestsNotifications.needTerminate()) {
|
||||
serverApiCommon.estimateFee(blockCount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// progressBar.visibility = View.INVISIBLE
|
||||
|
||||
fee = fee.setScale(8, RoundingMode.DOWN);
|
||||
|
||||
switch (blockCount) {
|
||||
case ServerApiCommon.ESTIMATE_FEE_MINIMAL: {
|
||||
CoinEngine.Amount minFee = new CoinEngine.Amount(fee, getFeeCurrency());
|
||||
feeRequestsNotifications.onComplete(true, minFee, null, null);
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbMinimalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
break;
|
||||
|
||||
case ServerApiCommon.ESTIMATE_FEE_NORMAL: {
|
||||
CoinEngine.Amount normalFee = new CoinEngine.Amount(fee, getFeeCurrency());
|
||||
feeRequestsNotifications.onComplete(true, null, normalFee, null);
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbNormalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
break;
|
||||
|
||||
case ServerApiCommon.ESTIMATE_FEE_PRIORITY: {
|
||||
CoinEngine.Amount maxFee = new CoinEngine.Amount(fee, getFeeCurrency());
|
||||
feeRequestsNotifications.onComplete(true, null, null, maxFee);
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbMaximumFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
}
|
||||
|
||||
// etFee.error = null
|
||||
// feeRequestSuccess = true
|
||||
// if (feeRequestSuccess)
|
||||
// if (feeRequestSuccess && balanceRequestSuccess)
|
||||
// btnSend.visibility = View.VISIBLE
|
||||
// dtVerified = Date()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String message) {
|
||||
feeRequestsNotifications.onComplete(false, null, null, null);
|
||||
|
||||
}
|
||||
};
|
||||
serverApiCommon.setEstimateFee(estimateFeeListener);
|
||||
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_PRIORITY);
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_NORMAL);
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_MINIMAL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public byte[] sign(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
//
|
||||
// checkBlockchainDataExists();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
package com.tangem.domain.wallet.eth;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.text.InputFilter;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.data.network.ServerApiInfura;
|
||||
import com.tangem.data.network.model.InfuraResponse;
|
||||
|
|
@ -12,19 +10,16 @@ import com.tangem.domain.wallet.BalanceValidator;
|
|||
import com.tangem.data.Blockchain;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
import com.tangem.domain.wallet.CoinEngineFactory;
|
||||
import com.tangem.domain.wallet.ECDSASignatureETH;
|
||||
import com.tangem.domain.wallet.EthTransaction;
|
||||
import com.tangem.domain.wallet.Keccak256;
|
||||
import com.tangem.domain.wallet.token.TokenData;
|
||||
import com.tangem.domain.wallet.token.TokenEngine;
|
||||
import com.tangem.tangemcard.data.TangemCard;
|
||||
import com.tangem.domain.wallet.TangemContext;
|
||||
import com.tangem.domain.wallet.BTCUtils;
|
||||
import com.tangem.tangemcard.tasks.SignTask;
|
||||
import com.tangem.util.CryptoUtil;
|
||||
import com.tangem.util.DecimalDigitsInputFilter;
|
||||
import com.tangem.util.UtilHelper;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
|
@ -462,7 +457,7 @@ public class EthEngine extends CoinEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void requestBalanceAndUnspentTransactions(BlockchainRequestsNotifications blockchainRequestsNotifications) throws Exception {
|
||||
public void requestBalanceAndUnspentTransactions(BalanceAndUnspentTransactionsNotifications balanceAndUnspentTransactionsNotifications) {
|
||||
final ServerApiInfura serverApiInfura = new ServerApiInfura();
|
||||
// request infura listener
|
||||
ServerApiInfura.InfuraBodyListener infuraBodyListener = new ServerApiInfura.InfuraBodyListener() {
|
||||
|
|
@ -473,8 +468,8 @@ public class EthEngine extends CoinEngine {
|
|||
String balanceCap = infuraResponse.getResult();
|
||||
balanceCap = balanceCap.substring(2);
|
||||
BigInteger l = new BigInteger(balanceCap, 16);
|
||||
BigInteger d = l.divide(new BigInteger("1000000000000000000", 10));
|
||||
Long balance = d.longValue();
|
||||
// BigInteger d = l.divide(new BigInteger("1000000000000000000", 10));
|
||||
// Long balance = d.longValue();
|
||||
|
||||
// (ctx.coinData!! as EthData).setBalanceConfirmed(balance)
|
||||
// (ctx.coinData!! as EthData).balanceUnconfirmed = 0L
|
||||
|
|
@ -510,102 +505,71 @@ public class EthEngine extends CoinEngine {
|
|||
|
||||
// Log.i("$TAG eth_getPendingTxCount", pending)
|
||||
}
|
||||
//
|
||||
case ServerApiInfura.INFURA_ETH_CALL: {
|
||||
try {
|
||||
String balanceCap = infuraResponse.getResult();
|
||||
balanceCap = balanceCap.substring(2);
|
||||
BigInteger l = new BigInteger(balanceCap, 16);
|
||||
Long balance = l.longValue();
|
||||
// if (l.compareTo(BigInteger.ZERO) == 0) {
|
||||
// //ctx.card!!.blockchainID = Blockchain.Ethereum.id
|
||||
// ctx.card!!.addTokenToBlockchainName()
|
||||
//
|
||||
// //TODO check
|
||||
// //ctx.blockchain=lBlockchain.Ethereum
|
||||
//
|
||||
// requestCounter--
|
||||
// if (requestCounter == 0) srl!!.isRefreshing = false
|
||||
//
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_BALANCE, "")
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_TRANSACTION_COUNT, "")
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_PENDING_COUNT, "")
|
||||
// return
|
||||
// }
|
||||
coinData.setBalanceInInternalUnits(new CoinEngine.InternalAmount(l, ctx.getCard().tokenSymbol));
|
||||
|
||||
// Log.i("$TAG eth_call", balanceCap)
|
||||
|
||||
if (!blockchainRequestsNotifications.needTerminate()) {
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_BALANCE, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, 67, coinData.getWallet(), "", "");
|
||||
} else {
|
||||
serverApiInfura.setErrorOccured("Terminated by user");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// ServerApiInfura.INFURA_ETH_SEND_RAW_TRANSACTION -> {
|
||||
// try {
|
||||
// var hashTX: String
|
||||
// try {
|
||||
// val tmp = infuraResponse.result
|
||||
// hashTX = tmp
|
||||
// } catch (e: JSONException) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// if (hashTX.startsWith("0x") || hashTX.startsWith("0X")) {
|
||||
// hashTX = hashTX.substring(2)
|
||||
// }
|
||||
//
|
||||
// Log.e("$TAG TX_RESULT", hashTX)
|
||||
//
|
||||
// val nonce = (ctx.coinData!! as EthData).confirmedTXCount
|
||||
// nonce.add(BigInteger.valueOf(1))
|
||||
// (ctx.coinData!! as EthData).confirmedTXCount = nonce
|
||||
//
|
||||
// Log.e("$TAG TX_RESULT", hashTX)
|
||||
//
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
//
|
||||
// counterMinus()
|
||||
|
||||
if (!serverApiInfura.hasRequests()) {
|
||||
blockchainRequestsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String method, String message) {
|
||||
if (!serverApiInfura.hasRequests()) {
|
||||
blockchainRequestsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
}
|
||||
}
|
||||
};
|
||||
serverApiInfura.setInfuraResponse(infuraBodyListener);
|
||||
|
||||
if (ctx.getBlockchain() == Blockchain.Ethereum || ctx.getBlockchain() == Blockchain.EthereumTestNet) {
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_BALANCE, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, 67, coinData.getWallet(), "", "");
|
||||
}
|
||||
}
|
||||
|
||||
// Token
|
||||
else if (ctx.getBlockchain() == Blockchain.Token) {
|
||||
final CoinEngine engine = CoinEngineFactory.INSTANCE.create(ctx);
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_CALL, 67, coinData.getWallet(), ((TokenEngine) engine).getContractAddress(ctx.getCard()), "");
|
||||
}
|
||||
@Override
|
||||
public void requestFee(FeeRequestsNotifications feeRequestsNotifications, CoinEngine.Amount amount) throws Exception {
|
||||
ServerApiInfura serverApiInfura = new ServerApiInfura();
|
||||
// request infura eth gasPrice listener
|
||||
ServerApiInfura.InfuraBodyListener infuraBodyListener = new ServerApiInfura.InfuraBodyListener() {
|
||||
@Override
|
||||
public void onSuccess(String method, InfuraResponse infuraResponse) {
|
||||
if(method== ServerApiInfura.INFURA_ETH_GAS_PRICE)
|
||||
{
|
||||
String gasPrice = infuraResponse.getResult();
|
||||
gasPrice = gasPrice.substring(2);
|
||||
// rounding gas price to integer gwei
|
||||
BigInteger l = new BigInteger(gasPrice, 16).divide(BigInteger.valueOf(1000000000L)).multiply(BigInteger.valueOf(1000000000L));
|
||||
|
||||
//val m = if (ctx.blockchain==Blockchain.Token) BigInteger.valueOf(60000) else BigInteger.valueOf(21000)
|
||||
BigInteger m;
|
||||
if (amount.getCurrency().equals("ETH")) m = BigInteger.valueOf(60000);
|
||||
else m = BigInteger.valueOf(21000);
|
||||
|
||||
// @Override
|
||||
CoinEngine.InternalAmount weiMinFee = new CoinEngine.InternalAmount(l.multiply(m), "wei");
|
||||
CoinEngine.InternalAmount weiNormalFee = new CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(12)).divide(BigDecimal.valueOf(10)), "wei");
|
||||
CoinEngine.InternalAmount weiMaxFee = new CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(15)).divide(BigDecimal.valueOf(10)), "wei");
|
||||
|
||||
CoinEngine.Amount minFee = convertToAmount(weiMinFee);
|
||||
CoinEngine.Amount normalFee = convertToAmount(weiNormalFee);
|
||||
CoinEngine.Amount maxFee = convertToAmount(weiMaxFee);
|
||||
feeRequestsNotifications.onComplete(true, minFee, normalFee, maxFee);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String method, String message) {
|
||||
if( method==ServerApiInfura.INFURA_ETH_GAS_PRICE ){
|
||||
feeRequestsNotifications.onComplete(false, null, null, null);
|
||||
}
|
||||
}
|
||||
};
|
||||
serverApiInfura.setInfuraResponse(infuraBodyListener);
|
||||
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GAS_PRICE, 67, coinData.getWallet(), "", "");
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public byte[] sign(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
//
|
||||
// BigInteger nonceValue = coinData.getConfirmedTXCount();
|
||||
|
|
@ -668,4 +632,4 @@ public class EthEngine extends CoinEngine {
|
|||
// byte[] realTX = tx.getEncoded();
|
||||
// return realTX;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@ import android.text.InputFilter;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.data.Blockchain;
|
||||
import com.tangem.data.network.ServerApiInfura;
|
||||
import com.tangem.data.network.model.InfuraResponse;
|
||||
import com.tangem.domain.wallet.BalanceValidator;
|
||||
import com.tangem.domain.wallet.CoinData;
|
||||
import com.tangem.domain.wallet.CoinEngine;
|
||||
|
|
@ -430,11 +433,6 @@ public class TokenEngine extends CoinEngine {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestBalanceAndUnspentTransactions(BlockchainRequestsNotifications blockchainRequestsNotifications) throws Exception {
|
||||
//TODO("NOT IMPLEMENTED")
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public byte[] sign(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
// if (amountValue.getCurrency().equals("ETH")) {
|
||||
|
|
@ -629,6 +627,113 @@ public class TokenEngine extends CoinEngine {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestBalanceAndUnspentTransactions(BalanceAndUnspentTransactionsNotifications balanceAndUnspentTransactionsNotifications) {
|
||||
final ServerApiInfura serverApiInfura = new ServerApiInfura();
|
||||
// request infura listener
|
||||
ServerApiInfura.InfuraBodyListener infuraBodyListener = new ServerApiInfura.InfuraBodyListener() {
|
||||
@Override
|
||||
public void onSuccess(String method, InfuraResponse infuraResponse) {
|
||||
switch (method) {
|
||||
case ServerApiInfura.INFURA_ETH_GET_BALANCE: {
|
||||
String balanceCap = infuraResponse.getResult();
|
||||
balanceCap = balanceCap.substring(2);
|
||||
BigInteger l = new BigInteger(balanceCap, 16);
|
||||
// BigInteger d = l.divide(new BigInteger("1000000000000000000", 10));
|
||||
// Long balance = d.longValue();
|
||||
|
||||
// (ctx.coinData!! as EthData).setBalanceConfirmed(balance)
|
||||
// (ctx.coinData!! as EthData).balanceUnconfirmed = 0L
|
||||
if (ctx.getBlockchain() != Blockchain.Token) {
|
||||
coinData.setBalanceReceived(true);
|
||||
coinData.setBalanceInInternalUnits(new CoinEngine.InternalAmount(l, "wei"));
|
||||
} else {
|
||||
coinData.setBalanceReceived(true);
|
||||
//(ctx.coinData!! as TokenData).balanceInInternalUnits = CoinEngine.InternalAmount(l.toBigDecimal(),ctx.card.tokenSymbol)
|
||||
((TokenData) coinData).setBalanceAlterInInternalUnits(new CoinEngine.InternalAmount(l, "wei"));
|
||||
}
|
||||
|
||||
// Log.i("$TAG eth_get_balance", balanceCap)
|
||||
}
|
||||
break;
|
||||
|
||||
case ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT: {
|
||||
String nonce = infuraResponse.getResult();
|
||||
nonce = nonce.substring(2);
|
||||
BigInteger count = new BigInteger(nonce, 16);
|
||||
coinData.setConfirmedTXCount(count);
|
||||
|
||||
|
||||
// Log.i("$TAG eth_getTransCount", nonce)
|
||||
}
|
||||
break;
|
||||
|
||||
case ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT: {
|
||||
String pending = infuraResponse.getResult();
|
||||
pending = pending.substring(2);
|
||||
BigInteger count = new BigInteger(pending, 16);
|
||||
coinData.setUnconfirmedTXCount(count);
|
||||
|
||||
// Log.i("$TAG eth_getPendingTxCount", pending)
|
||||
}
|
||||
//
|
||||
case ServerApiInfura.INFURA_ETH_CALL: {
|
||||
try {
|
||||
String balanceCap = infuraResponse.getResult();
|
||||
balanceCap = balanceCap.substring(2);
|
||||
BigInteger l = new BigInteger(balanceCap, 16);
|
||||
Long balance = l.longValue();
|
||||
// if (l.compareTo(BigInteger.ZERO) == 0) {
|
||||
// //ctx.card!!.blockchainID = Blockchain.Ethereum.id
|
||||
// ctx.card!!.addTokenToBlockchainName()
|
||||
//
|
||||
// //TODO check
|
||||
// //ctx.blockchain=lBlockchain.Ethereum
|
||||
//
|
||||
// requestCounter--
|
||||
// if (requestCounter == 0) srl!!.isRefreshing = false
|
||||
//
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_BALANCE, "")
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_TRANSACTION_COUNT, "")
|
||||
// requestInfura(ServerApiCommon.INFURA_ETH_GET_PENDING_COUNT, "")
|
||||
// return
|
||||
// }
|
||||
coinData.setBalanceInInternalUnits(new CoinEngine.InternalAmount(l, ctx.getCard().tokenSymbol));
|
||||
|
||||
// Log.i("$TAG eth_call", balanceCap)
|
||||
|
||||
if (!balanceAndUnspentTransactionsNotifications.needTerminate()) {
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_BALANCE, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_TRANSACTION_COUNT, 67, coinData.getWallet(), "", "");
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_GET_PENDING_COUNT, 67, coinData.getWallet(), "", "");
|
||||
} else {
|
||||
serverApiInfura.setErrorOccured("Terminated by user");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!serverApiInfura.hasRequests()) {
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFail(String method, String message) {
|
||||
if (!serverApiInfura.hasRequests()) {
|
||||
balanceAndUnspentTransactionsNotifications.onComplete(serverApiInfura.isErrorOccured());
|
||||
}
|
||||
}
|
||||
};
|
||||
serverApiInfura.setInfuraResponse(infuraBodyListener);
|
||||
|
||||
serverApiInfura.infura(ServerApiInfura.INFURA_ETH_CALL, 67, coinData.getWallet(), getContractAddress(ctx.getCard()), "");
|
||||
}
|
||||
|
||||
|
||||
// public byte[] signETH(Amount feeValue, Amount amountValue, boolean IncFee, String targetAddress, CardProtocol protocol) throws Exception {
|
||||
// BigInteger nonceValue = coinData.getConfirmedTXCount();
|
||||
// byte[] pbKey = ctx.getCard().getWalletPublicKey();
|
||||
|
|
|
|||
|
|
@ -42,15 +42,15 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
private var nfcManager: NfcManager? = null
|
||||
|
||||
private var serverApiCommon: ServerApiCommon = ServerApiCommon()
|
||||
private var serverApiInfura: ServerApiInfura = ServerApiInfura()
|
||||
private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
|
||||
// private var serverApiCommon: ServerApiCommon = ServerApiCommon()
|
||||
// private var serverApiInfura: ServerApiInfura = ServerApiInfura()
|
||||
// private var serverApiElectrum: ServerApiElectrum = ServerApiElectrum()
|
||||
|
||||
private lateinit var ctx: TangemContext
|
||||
private lateinit var amount: CoinEngine.Amount
|
||||
|
||||
private var feeRequestSuccess = false
|
||||
// private var balanceRequestSuccess = false
|
||||
// private var balanceRequestSuccess = false
|
||||
private var minFee: CoinEngine.Amount? = null
|
||||
private var maxFee: CoinEngine.Amount? = null
|
||||
private var normalFee: CoinEngine.Amount? = null
|
||||
|
|
@ -58,7 +58,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
private var requestPIN2Count = 0
|
||||
private var nodeCheck = true
|
||||
private var dtVerified: Date? = null
|
||||
private var calcSize: Int = 0
|
||||
// private var calcSize: Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
|
@ -84,7 +84,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
amount = CoinEngine.Amount(intent.getStringExtra(SignPaymentActivity.EXTRA_AMOUNT), intent.getStringExtra(SignPaymentActivity.EXTRA_AMOUNT_CURRENCY))
|
||||
|
||||
if (ctx.blockchain == Blockchain.Token && amount.currency!="ETH")
|
||||
if (ctx.blockchain == Blockchain.Token && amount.currency != "ETH")
|
||||
tvIncFee.visibility = View.INVISIBLE
|
||||
else
|
||||
tvIncFee.visibility = View.VISIBLE
|
||||
|
|
@ -103,7 +103,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
if (ctx.blockchain == Blockchain.Ethereum || ctx.blockchain == Blockchain.EthereumTestNet || ctx.blockchain == Blockchain.Token) {
|
||||
rgFee.isEnabled = false
|
||||
|
||||
requestInfura(ServerApiInfura.INFURA_ETH_GAS_PRICE)
|
||||
// requestInfura(ServerApiInfura.INFURA_ETH_GAS_PRICE)
|
||||
|
||||
} else {
|
||||
rgFee.isEnabled = true
|
||||
|
|
@ -114,7 +114,7 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
progressBar.visibility = View.VISIBLE
|
||||
|
||||
requestEstimateFee()
|
||||
// requestEstimateFee()
|
||||
}
|
||||
|
||||
// set listeners
|
||||
|
|
@ -192,6 +192,33 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
startActivityForResult(intent, REQUEST_CODE_REQUEST_PIN2)
|
||||
}
|
||||
|
||||
val coinEngine = CoinEngineFactory.create(ctx)
|
||||
coinEngine!!.requestFee(
|
||||
object : CoinEngine.FeeRequestsNotifications {
|
||||
override fun onComplete(success: Boolean, minFee: CoinEngine.Amount?, normalFee: CoinEngine.Amount?, maxFee: CoinEngine.Amount?) {
|
||||
if (success) {
|
||||
this@ConfirmPaymentActivity.minFee = minFee
|
||||
this@ConfirmPaymentActivity.normalFee = normalFee
|
||||
this@ConfirmPaymentActivity.maxFee = maxFee
|
||||
doSetFee(rgFee.checkedRadioButtonId)
|
||||
etFee.error = null
|
||||
btnSend.visibility = View.VISIBLE
|
||||
feeRequestSuccess = true
|
||||
// balanceRequestSuccess = true
|
||||
dtVerified = Date()
|
||||
} else {
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
}
|
||||
}
|
||||
|
||||
override fun needTerminate(): Boolean {
|
||||
return !UtilHelper.isOnline(this@ConfirmPaymentActivity)
|
||||
}
|
||||
},
|
||||
amount
|
||||
)
|
||||
|
||||
|
||||
// request electrum listener
|
||||
// val electrumBodyListener: ServerApiHelperElectrum.ElectrumRequestDataListener = object : ServerApiHelperElectrum.ElectrumRequestDataListener {
|
||||
// override fun onSuccess(electrumRequest: ElectrumRequest?) {
|
||||
|
|
@ -227,97 +254,97 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
// serverApiHelperElectrum.setElectrumRequestData(electrumBodyListener)
|
||||
|
||||
// request infura eth gasPrice listener
|
||||
val infuraBodyListener: ServerApiInfura.InfuraBodyListener = object : ServerApiInfura.InfuraBodyListener {
|
||||
override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
|
||||
when (method) {
|
||||
ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
|
||||
var gasPrice = infuraResponse.result
|
||||
gasPrice = gasPrice.substring(2)
|
||||
//TODO - remove Gwei
|
||||
// rounding gas price to integer gwei
|
||||
val l = BigInteger(gasPrice, 16).divide(BigInteger.valueOf(1000000000L)).multiply(BigInteger.valueOf(1000000000L))
|
||||
// val infuraBodyListener: ServerApiInfura.InfuraBodyListener = object : ServerApiInfura.InfuraBodyListener {
|
||||
// override fun onSuccess(method: String, infuraResponse: InfuraResponse) {
|
||||
// when (method) {
|
||||
// ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
|
||||
// var gasPrice = infuraResponse.result
|
||||
// gasPrice = gasPrice.substring(2)
|
||||
// //TODO - remove Gwei
|
||||
// // rounding gas price to integer gwei
|
||||
// val l = BigInteger(gasPrice, 16).divide(BigInteger.valueOf(1000000000L)).multiply(BigInteger.valueOf(1000000000L))
|
||||
//
|
||||
// //val m = if (ctx.blockchain==Blockchain.Token) BigInteger.valueOf(60000) else BigInteger.valueOf(21000)
|
||||
// val m = if (amount.currency != "ETH") BigInteger.valueOf(60000) else BigInteger.valueOf(21000)
|
||||
// val weiMinFee = CoinEngine.InternalAmount(l.multiply(m), "wei")
|
||||
// val weiNormalFee = CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(12)).divide(BigDecimal.valueOf(10)), "wei")
|
||||
// val weiMaxFee = CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(15)).divide(BigDecimal.valueOf(10)), "wei")
|
||||
//
|
||||
// minFee = engine.convertToAmount(weiMinFee)
|
||||
// normalFee = engine.convertToAmount(weiNormalFee)
|
||||
// maxFee = engine.convertToAmount(weiMaxFee)
|
||||
// doSetFee(rgFee.checkedRadioButtonId)
|
||||
// //etFee.setText(weiNormalFee.toValueString())
|
||||
// etFee.error = null
|
||||
// btnSend.visibility = View.VISIBLE
|
||||
// feeRequestSuccess = true
|
||||
//// balanceRequestSuccess = true
|
||||
// dtVerified = Date()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun onFail(method: String, message: String) {
|
||||
// when (method) {
|
||||
// ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
|
||||
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// serverApiInfura.setInfuraResponse(infuraBodyListener)
|
||||
|
||||
//val m = if (ctx.blockchain==Blockchain.Token) BigInteger.valueOf(60000) else BigInteger.valueOf(21000)
|
||||
val m = if (amount.currency != "ETH") BigInteger.valueOf(60000) else BigInteger.valueOf(21000)
|
||||
val weiMinFee = CoinEngine.InternalAmount(l.multiply(m), "wei")
|
||||
val weiNormalFee = CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(12)).divide(BigDecimal.valueOf(10)), "wei")
|
||||
val weiMaxFee = CoinEngine.InternalAmount(weiMinFee.multiply(BigDecimal.valueOf(15)).divide(BigDecimal.valueOf(10)), "wei")
|
||||
|
||||
minFee = engine.convertToAmount(weiMinFee)
|
||||
normalFee = engine.convertToAmount(weiNormalFee)
|
||||
maxFee = engine.convertToAmount(weiMaxFee)
|
||||
doSetFee(rgFee.checkedRadioButtonId)
|
||||
//etFee.setText(weiNormalFee.toValueString())
|
||||
etFee.error = null
|
||||
btnSend.visibility = View.VISIBLE
|
||||
feeRequestSuccess = true
|
||||
// balanceRequestSuccess = true
|
||||
dtVerified = Date()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFail(method: String, message: String) {
|
||||
when (method) {
|
||||
ServerApiInfura.INFURA_ETH_GAS_PRICE -> {
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
serverApiInfura.setInfuraResponse(infuraBodyListener)
|
||||
|
||||
// request estimate fee listener
|
||||
val estimateFeeListener: ServerApiCommon.EstimateFeeListener = object : ServerApiCommon.EstimateFeeListener {
|
||||
override fun onSuccess(blockCount: Int, estimateFeeResponse: String?) {
|
||||
var fee: BigDecimal?
|
||||
fee = BigDecimal(estimateFeeResponse) // BTC per 1 kb
|
||||
|
||||
if (fee == BigDecimal.ZERO) {
|
||||
progressBar.visibility = View.INVISIBLE
|
||||
requestEstimateFee()
|
||||
}
|
||||
|
||||
if (calcSize.toLong() != 0L) {
|
||||
fee = fee.multiply(BigDecimal(calcSize.toLong())).divide(BigDecimal(1024)) // per Kb -> per byte
|
||||
} else {
|
||||
requestEstimateFee()
|
||||
}
|
||||
|
||||
progressBar.visibility = View.INVISIBLE
|
||||
|
||||
fee = fee!!.setScale(8, RoundingMode.DOWN)
|
||||
|
||||
when (blockCount) {
|
||||
ServerApiCommon.ESTIMATE_FEE_MINIMAL -> {
|
||||
minFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
if (rgFee.checkedRadioButtonId == R.id.rbMinimalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
|
||||
ServerApiCommon.ESTIMATE_FEE_NORMAL -> {
|
||||
normalFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
if (rgFee.checkedRadioButtonId == R.id.rbNormalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
|
||||
ServerApiCommon.ESTIMATE_FEE_PRIORITY -> {
|
||||
maxFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
if (rgFee.checkedRadioButtonId == R.id.rbMaximumFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
}
|
||||
}
|
||||
|
||||
etFee.error = null
|
||||
feeRequestSuccess = true
|
||||
if (feeRequestSuccess)
|
||||
// if (feeRequestSuccess && balanceRequestSuccess)
|
||||
btnSend.visibility = View.VISIBLE
|
||||
dtVerified = Date()
|
||||
}
|
||||
|
||||
override fun onFail(message: String?) {
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_calculate_fee_wrong_data_received_from_node))
|
||||
}
|
||||
}
|
||||
serverApiCommon.setEstimateFee(estimateFeeListener)
|
||||
// // request estimate fee listener
|
||||
// val estimateFeeListener: ServerApiCommon.EstimateFeeListener = object : ServerApiCommon.EstimateFeeListener {
|
||||
// override fun onSuccess(blockCount: Int, estimateFeeResponse: String?) {
|
||||
// var fee: BigDecimal?
|
||||
// fee = BigDecimal(estimateFeeResponse) // BTC per 1 kb
|
||||
//
|
||||
// if (fee == BigDecimal.ZERO) {
|
||||
// progressBar.visibility = View.INVISIBLE
|
||||
// requestEstimateFee()
|
||||
// }
|
||||
//
|
||||
// if (calcSize.toLong() != 0L) {
|
||||
// fee = fee.multiply(BigDecimal(calcSize.toLong())).divide(BigDecimal(1024)) // per Kb -> per byte
|
||||
// } else {
|
||||
// requestEstimateFee()
|
||||
// }
|
||||
//
|
||||
// progressBar.visibility = View.INVISIBLE
|
||||
//
|
||||
// fee = fee!!.setScale(8, RoundingMode.DOWN)
|
||||
//
|
||||
// when (blockCount) {
|
||||
// ServerApiCommon.ESTIMATE_FEE_MINIMAL -> {
|
||||
// minFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbMinimalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
// }
|
||||
//
|
||||
// ServerApiCommon.ESTIMATE_FEE_NORMAL -> {
|
||||
// normalFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbNormalFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
// }
|
||||
//
|
||||
// ServerApiCommon.ESTIMATE_FEE_PRIORITY -> {
|
||||
// maxFee = CoinEngine.Amount(fee, engine.feeCurrency)
|
||||
// if (rgFee.checkedRadioButtonId == R.id.rbMaximumFee) doSetFee(rgFee.checkedRadioButtonId)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// etFee.error = null
|
||||
// feeRequestSuccess = true
|
||||
// if (feeRequestSuccess)
|
||||
//// if (feeRequestSuccess && balanceRequestSuccess)
|
||||
// btnSend.visibility = View.VISIBLE
|
||||
// dtVerified = Date()
|
||||
// }
|
||||
//
|
||||
// override fun onFail(message: String?) {
|
||||
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_calculate_fee_wrong_data_received_from_node))
|
||||
// }
|
||||
// }
|
||||
// serverApiCommon.setEstimateFee(estimateFeeListener)
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
|
|
@ -394,98 +421,35 @@ class ConfirmPaymentActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
|||
|
||||
// TODO - move to BtcEngine
|
||||
@Throws(Exception::class)
|
||||
internal fun buildSize(outputAddress: String, outFee: String, outAmount: String): Int {
|
||||
val myAddress = ctx.coinData!!.wallet
|
||||
val pbKey = ctx.card!!.walletPublicKey
|
||||
val pbComprKey = ctx.card!!.walletPublicKeyRar
|
||||
|
||||
// build script for our address
|
||||
val rawTxList = (ctx.coinData!! as BtcData).unspentTransactions
|
||||
val outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes
|
||||
// private fun requestElectrum(ctx: TangemContext, electrumRequest: ElectrumRequest) {
|
||||
// if (UtilHelper.isOnline(this)) {
|
||||
// serverApiElectrum.electrumRequestData(ctx, electrumRequest)
|
||||
// } else
|
||||
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
// }
|
||||
|
||||
// collect unspent
|
||||
val unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend)
|
||||
// private fun requestInfura(method: String) {
|
||||
// if (UtilHelper.isOnline(this)) {
|
||||
// serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, "", "")
|
||||
// } else
|
||||
// finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
// }
|
||||
|
||||
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 -= 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
|
||||
}
|
||||
|
||||
private fun requestElectrum(ctx: TangemContext, electrumRequest: ElectrumRequest) {
|
||||
if (UtilHelper.isOnline(this)) {
|
||||
serverApiElectrum.electrumRequestData(ctx, electrumRequest)
|
||||
} else
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
}
|
||||
|
||||
private fun requestInfura(method: String) {
|
||||
if (UtilHelper.isOnline(this)) {
|
||||
serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, "", "")
|
||||
} else
|
||||
finishWithError(Activity.RESULT_CANCELED, getString(R.string.cannot_obtain_data_from_blockchain))
|
||||
}
|
||||
|
||||
private fun requestEstimateFee() {
|
||||
if( calcSize==0 )
|
||||
{
|
||||
calcSize = 256
|
||||
try {
|
||||
|
||||
calcSize = buildSize(etWallet!!.text.toString(), "0.00", etAmount.text.toString())
|
||||
} catch (ex: Exception) {
|
||||
Log.e("Build Fee error", ex.message)
|
||||
}
|
||||
}
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_PRIORITY)
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_NORMAL)
|
||||
serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_MINIMAL)
|
||||
}
|
||||
// private fun requestEstimateFee() {
|
||||
// if (calcSize == 0) {
|
||||
// calcSize = 256
|
||||
// try {
|
||||
//
|
||||
// calcSize = buildSize(etWallet!!.text.toString(), "0.00", etAmount.text.toString())
|
||||
// } catch (ex: Exception) {
|
||||
// Log.e("Build Fee error", ex.message)
|
||||
// }
|
||||
// }
|
||||
// serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_PRIORITY)
|
||||
// serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_NORMAL)
|
||||
// serverApiCommon.estimateFee(ServerApiCommon.ESTIMATE_FEE_MINIMAL)
|
||||
// }
|
||||
|
||||
private fun doSetFee(checkedRadioButtonId: Int) {
|
||||
var txtFee = ""
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
nfcManager!!.notifyReadResult(false)
|
||||
nfcManager.notifyReadResult(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,11 +279,11 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
super.onResume()
|
||||
animate()
|
||||
ReadCardInfoTask.resetLastReadInfo()
|
||||
nfcManager!!.onResume()
|
||||
nfcManager.onResume()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
nfcManager!!.onPause()
|
||||
nfcManager.onPause()
|
||||
if (readCardInfoTask != null) {
|
||||
readCardInfoTask!!.cancel(true)
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
|
|||
|
||||
public override fun onStop() {
|
||||
// dismiss enable NFC dialog
|
||||
nfcManager!!.onStop()
|
||||
nfcManager.onStop()
|
||||
if (readCardInfoTask != null) {
|
||||
readCardInfoTask!!.cancel(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,24 +22,17 @@ import android.widget.Toast
|
|||
import com.tangem.App
|
||||
import com.tangem.Constant
|
||||
import com.tangem.data.network.ServerApiCommon
|
||||
import com.tangem.data.network.ServerApiInfura
|
||||
import com.tangem.tangemserver.android.model.CardVerifyAndGetInfo
|
||||
import com.tangem.data.network.model.InfuraResponse
|
||||
import com.tangem.tangemcard.tasks.VerifyCardTask
|
||||
import com.tangem.tangemcard.reader.CardProtocol
|
||||
import com.tangem.tangemcard.android.reader.NfcManager
|
||||
import com.tangem.domain.wallet.*
|
||||
import com.tangem.domain.wallet.bch.BtcCashEngine
|
||||
import com.tangem.domain.wallet.eth.EthData
|
||||
import com.tangem.domain.wallet.token.TokenData
|
||||
import com.tangem.domain.wallet.token.TokenEngine
|
||||
import com.tangem.presentation.activity.*
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog
|
||||
import com.tangem.presentation.dialog.PINSwapWarningDialog
|
||||
import com.tangem.presentation.dialog.ShowQRCodeDialog
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.data.Blockchain
|
||||
import com.tangem.data.network.ElectrumRequest
|
||||
import com.tangem.tangemcard.android.reader.NfcReader
|
||||
import com.tangem.tangemcard.data.EXTRA_TANGEM_CARD
|
||||
import com.tangem.tangemcard.data.EXTRA_TANGEM_CARD_UID
|
||||
|
|
@ -50,9 +43,7 @@ import com.tangem.tangemserver.android.ServerApiTangem
|
|||
import com.tangem.util.UtilHelper
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fr_loaded_wallet.*
|
||||
import org.json.JSONException
|
||||
import java.io.InputStream
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
|
@ -802,23 +793,21 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
|
||||
requestVerifyAndGetInfo()
|
||||
|
||||
if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet || ctx.blockchain == Blockchain.BitcoinCash) {
|
||||
val coinEngine = CoinEngineFactory.create(ctx)
|
||||
requestCounter++
|
||||
coinEngine!!.requestBalanceAndUnspentTransactions(
|
||||
object : CoinEngine.BlockchainRequestsNotifications {
|
||||
override fun onComplete(success: Boolean?) {
|
||||
counterMinus()
|
||||
updateViews()
|
||||
}
|
||||
|
||||
override fun needTerminate(): Boolean {
|
||||
return !UtilHelper.isOnline(context as Activity)
|
||||
}
|
||||
val coinEngine = CoinEngineFactory.create(ctx)
|
||||
requestCounter++
|
||||
coinEngine!!.requestBalanceAndUnspentTransactions(
|
||||
object : CoinEngine.BalanceAndUnspentTransactionsNotifications {
|
||||
override fun onComplete(success: Boolean?) {
|
||||
counterMinus()
|
||||
updateViews()
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
override fun needTerminate(): Boolean {
|
||||
return !UtilHelper.isOnline(context as Activity)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// Bitcoin
|
||||
if (ctx.blockchain == Blockchain.Bitcoin || ctx.blockchain == Blockchain.BitcoinTestNet) {
|
||||
|
|
@ -865,15 +854,15 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
// }
|
||||
// }
|
||||
|
||||
private fun requestInfura(method: String, contract: String) {
|
||||
if (UtilHelper.isOnline(context as Activity)) {
|
||||
requestCounter++
|
||||
serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, contract, "")
|
||||
} else {
|
||||
Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
||||
srl?.isRefreshing = false
|
||||
}
|
||||
}
|
||||
// private fun requestInfura(method: String, contract: String) {
|
||||
// if (UtilHelper.isOnline(context as Activity)) {
|
||||
// requestCounter++
|
||||
// serverApiInfura.infura(method, 67, ctx.coinData!!.wallet, contract, "")
|
||||
// } else {
|
||||
// Toast.makeText(activity, getString(R.string.no_connection), Toast.LENGTH_SHORT).show()
|
||||
// srl?.isRefreshing = false
|
||||
// }
|
||||
// }
|
||||
|
||||
private fun requestVerifyAndGetInfo() {
|
||||
if (UtilHelper.isOnline(context as Activity)) {
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class LocalStorage
|
|||
var sData: String? = result.substitution?.data
|
||||
var sSignature: String? = result.substitution?.signature
|
||||
if (card.batch != result.batch) {
|
||||
Log.e("CardDataSubstitutionProvider", "Invalid batch received!")
|
||||
Log.e("CardDataSubstitution", "Invalid batch received!")
|
||||
return false
|
||||
}
|
||||
if (!BatchInfo.CardDataSubstitution.verifySignature(card, sData, sSignature)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue